GIDForums  

Go Back   GIDForums > Computer Programming Forums > C Programming Language
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 04-Apr-2004, 23:59
nusstu nusstu is offline
New Member
 
Join Date: Mar 2004
Posts: 27
nusstu is on a distinguished road

Strange behaviour in printf (interesting)


Hi,
I was doing one of my lab and had this very strange bug. It's a very simple program, it processes 2 commands namely "prompt <sth>" which changes the prompt to <sth> and "exit 0" which exits. (The program isn;t as long as u think )

Here's the code:
CPP / C++ / C Code:
#include <stdio.h>
#include <string.h>

//GLOBAL VARIABLES
char *seps = " \n";  //stores delimiters
char prompt[256];    //stores prompt
char buffer[256];    //stores buffer
char *cmds = "echo prompt exit status repeat wait background noop %";  //a string to store all internal commands

//FUNCTIONS
int changePrompt ();
int Prompt(int flag);
void Exit (int status);

int main(int argc, char *argv[]) {

  strcpy(prompt,"mysh"); //initialise default prompt.

  if ((argc != 2) && (argc != 1)) 
    puts("Error: Wrong no. of arguments.");
  
  //no arguments - std input
  else if (argc == 1) {
    Prompt(0);
  }//else if

  //one argument - test script file
  else {
    FILE *fp;

    //error opening file
    if ((fp = fopen(argv[1], "r")) == NULL) {
      fprintf(stderr, "Error opening file.\n");
    }//if

    else {
      while (!feof(fp)) {
	if (fgets(buffer,256, fp) != NULL)  //read test script file line by line.
	  Prompt(1);
      }//while

      fclose(fp);
    }//else
    
  }//else

  return 0;

}//main


//flag = 0 => read from stdin
//flag = 1 => read from test script file 

int Prompt(int flag) {  
  
  char *token;
  char *test;  
  int result = 0;
  char local_buffer[256];

  while (1) {
    puts(prompt);
    printf("%s>", prompt);
    if (flag == 0) 
      fgets(buffer, 256, stdin);  

    strcpy(local_buffer, buffer);
    printf("before buffer:%s",local_buffer);
    token = strtok(local_buffer, seps);
    printf("after buffer:%s",local_buffer);

    if (token == NULL)  //<newline> command
      continue;
    
    //internal command
    else
      result = InternalCmdHandler(flag, token);

    if (flag == 1){
      return result;
      break;
    }//if 

  }//while

}//Prompt

int InternalCmdHandler(int flag, char *token) {
  
  //exit
  if (strcasecmp(token,"exit") == 0) {
    token = strtok(NULL, seps);
    Exit(atoi(token));  //there's nothing to return here because exit always succeeds.
  }//if
    
  //prompt
  else if (strcasecmp(token,"prompt") == 0) {    
    if (flag == 1)
      printf("\n");  //for aesthetic reason

    return changePrompt();     
  }//else if
    
}//InternalCmdHandler
 
int changePrompt () {
  char *new_prompt = strtok(buffer,seps);
  new_prompt = strtok(NULL, seps);

  if (new_prompt == NULL)
    strcpy(prompt,"\0");
  else  
    strcpy(prompt,new_prompt);  

  //printf("%c",prompt[0]);
  return 0;
}//changePrompt
 
void Exit (int status) {
  puts("\nBye!");
  exit(status);
}//Exit
------I dunno why the tags don't work but i attached it below (rename to .c)-------------------
There're 2 modes of entering input (1) File (2)stdin.
The file contains 2 lines :
prompt bash
exit 0

to run simply use:
> ./a.out <filename> //i attached test.txt for <filename>

NOTE: You can ignore the before buffer, after buffer thingy that just shows that strtok() messes with the input string.

Here're the STRANGE problems:
You'll notice i printed the prompt twice using puts and printf. The STRANGE thing is after the command "prompt bash" is read, puts displays bash BUT printf displays NULL ???

I'd be very grateful if anyone can explain this STRANGE behaviours.
Attached Files
File Type: txt strange.txt (2.4 KB, 21 views)
File Type: txt test.txt (21 Bytes, 15 views)
Last edited by JdS : 05-Apr-2004 at 05:11. Reason: fixed missing closing C BBCode
  #2  
Old 05-Apr-2004, 02:11
aaroncohn's Avatar
aaroncohn aaroncohn is offline
Regular Member
 
Join Date: Feb 2004
Location: Bay Area, CA.
Posts: 564
aaroncohn is a jewel in the roughaaroncohn is a jewel in the roughaaroncohn is a jewel in the rough
The tags don't work because you were holding the shift key when you typed the ending bracket, causing you to use a brace instead of a bracket.
__________________
-Aaron
  #3  
Old 05-Apr-2004, 02:21
WaltP's Avatar
WaltP WaltP is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Midwest US
Posts: 3,335
WaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to all
Quote:
Originally Posted by nusstu
Hi,
I was doing one of my lab and had this very strange bug. It's a very simple program, it processes 2 commands namely "prompt <sth>" which changes the prompt to <sth> and "exit 0" which exits. (The program isn;t as long as u think )
I think it's 124 lines long, with no formatting. How long is it really?

Quote:
Originally Posted by nusstu
Here's the code:
[c]
#include <stdio.h>
#include <string.h>
...
void Exit (int status) {
puts("\nBye!");
exit(status);
}//Exit
[/C}------I dunno why the tags don't work but i attached it below (rename to .c)-------------------
Because you have to use them correctly: [/C]
Quote:
Originally Posted by nusstu
There're 2 modes of entering input (1) File (2)stdin.
The file contains 2 lines :
prompt bash
exit 0

to run simply use:
> ./a.out <filename> //i attached test.txt for <filename>

NOTE: You can ignore the before buffer, after buffer thingy that just shows that strtok() messes with the input string.

Here're the STRANGE problems:
You'll notice i printed the prompt twice using puts and printf. The STRANGE thing is after the command "prompt bash" is read, puts displays bash BUT printf displays NULL ???

I'd be very grateful if anyone can explain this STRANGE behaviours.
All I get are a bunch of warnings:
Quote:
Warning W8065 x.c 79: Call to function 'InternalCmdHandler' with no rototype in function Prompt
Warning W8066 x.c 83: Unreachable code in function Prompt
Warning W8070 x.c 88: Function should return a value in function Prompt
Warning W8004 x.c 60: 'result' is assigned a value that is never used in function Prompt
Warning W8065 x.c 93: Call to function 'strcasecmp' with no prototype in function InternalCmdHandler
Warning W8065 x.c 95: Call to function 'atoi' with no prototype in function InternalCmdHandler
Warning W8065 x.c 99: Call to function 'strcasecmp' with no prototype in function InternalCmdHandler
Warning W8065 x.c 103: Call to function 'changePrompt' with no prototype in function InternalCmdHandler
Warning W8070 x.c 106: Function should return a value in function InternalCmdHandler
Warning W8004 x.c 109: 'new_prompt' is assigned a value that is never used in function changePrompt
Warning W8065 x.c 123: Call to function 'exit' with no prototype in function Exit
I'm not willing to fix all these problems to see what your output is... and use standard functions because we're not all running Linux (strcasecmp is not standard)
__________________

During the election they said Obama could only be elected when pigs fly. Well, we currently have an epidemic of Swine Flu. Coincidence?
  #4  
Old 05-Apr-2004, 05:47
nusstu nusstu is offline
New Member
 
Join Date: Mar 2004
Posts: 27
nusstu is on a distinguished road
Hi WaltP,

Sorry about that, I've given a much shorter program below that is Windows compliant I hope. Please run it as ./a.out test1.txt (attached below)

Quote:
Originally Posted by WaltP
I I'm not willing to fix all these problems to see what your output is... and use standard functions because we're not all running Linux (strcasecmp is not standard)

CPP / C++ / C Code:
#include <stdio.h>
#include <string.h>

char *seps = " \n";
char prompt[256];
char buffer[256];

void changePrompt ();

int main(int argc, char *argv[]) {
  FILE *fp;

  strcpy(prompt,"mysh");
  if ((fp = fopen(argv[1], "r")) == NULL) {
    fprintf(stderr, "Error opening file.\n");
  }//if

  else {
    while (!feof(fp)) {
      if (fgets(buffer,256, fp) != NULL)  //read test script file line by line.
	Prompt();
    }//while

    fclose(fp);
  }//else
   
}//main

int Prompt() {
  char *token;
  char *test;
  char local_buffer[256];

  puts(prompt);
  printf("%s>", prompt);

  //copy buffer to local_buffer cos strtok messes input string.
  strcpy(local_buffer, buffer);
  printf("before buffer:%s",local_buffer);
  token = strtok(local_buffer, seps);  
  printf("after buffer:%s",local_buffer);
  
  //puts("pass");  //Strangely, adding this line displays the printf before correctly.

  changePrompt();
}//Prompt

void changePrompt () {
  char *new_prompt = strtok(buffer,seps);   
  new_prompt = strtok(NULL, seps);
  
  if (new_prompt == NULL)
    strcpy(prompt,"\0");
  else  
    strcpy(prompt,new_prompt);  

  printf("%s",prompt);

}//changePrompt

You'll notice the difference removing and adding the line puts("pass");
Attached Files
File Type: txt test1.txt (13 Bytes, 13 views)
  #5  
Old 05-Apr-2004, 09:03
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 5,218
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold
Here's a suggestion: make your debug printf()s more informative. For example

CPP / C++ / C Code:
  strcpy(local_buffer, buffer);
  printf("before strtok, local_buffer: <%s>",local_buffer);
  token = strtok(local_buffer, seps);  
  printf("after strtok, local_buffer: <%s>",local_buffer);

and

CPP / C++ / C Code:
  printf("Entering changePrompt(), prompt: <%s>\n",prompt);
  if (new_prompt == NULL)
    strcpy(prompt,"\0");
  else  
    strcpy(prompt,new_prompt);  

  printf("Leaving changePrompt(), prompt: <%s>\n",prompt);

Notice that the angle brackets '<' and '>' delineate exactly what the heck the string is.

All together, now:

"printf() is your friend"

Dave

(There is nothing mysterious here, you just didn't see what you were looking for. I don't think that I've ever seen printf() get confused; just me, from time to time.)
  #6  
Old 05-Apr-2004, 09:09
dsmith's Avatar
dsmith dsmith is offline
Senior Member
 
Join Date: Jan 2004
Location: Utah, USA
Posts: 1,351
dsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of light
Hi nusstu.

I am not 100% sure what is going on. If I change the printf statement to:
CPP / C++ / C Code:
printf("after buffer:%s\n",local_buffer);
(notice the newline). I get the printout with or without the puts.

I think the root of the problem is strtok. It is not a highly recommended function and I don't think that I would trust what is in local_buffer after a call to strtok.

Here, again, are some choice quotes about strtok:
Quote:
Never use these functions. If you do, note that:

These functions modify their first argument.

Quote:
The strtok() function can be used to parse the string s
into tokens. The first call to strtok() should have s as
its first argument. Subsequent calls should have the first
argument set to NULL. Each call returns a pointer to the
next token, or NULL when no more tokens are found.

If you don't want to write your own parser that is fine, but make sure that you know what you are getting when you use strtok. Basically after the first call to strtok, your local_buffer variable should not be used again.

HTH
d
  #7  
Old 05-Apr-2004, 09:58
nusstu nusstu is offline
New Member
 
Join Date: Mar 2004
Posts: 27
nusstu is on a distinguished road
Hi dsmith,

I know that adding "\n" will print the stuff to screen because printf is line buffered. But, shouldn't it still print if i used fflush(stdout); The point is I don't want it to go to the next line.
Here's an updated version of the program using fflush(stdout):

CPP / C++ / C Code:
#include <stdio.h>
#include <string.h>

char *seps = " \n";
char prompt[256];
char buffer[256];

void changePrompt ();

int main(int argc, char *argv[]) {
  FILE *fp;

  strcpy(prompt,"mysh");
  if ((fp = fopen(argv[1], "r")) == NULL) {
    fprintf(stderr, "Error opening file.\n");
  }//if

  else {
    while (!feof(fp)) {
      if (fgets(buffer,256, fp) != NULL)  //read test script file line by line.
	Prompt();
    }//while

    fclose(fp);
  }//else
   
}//main

int Prompt() {
  char *token;
  char *test;
  char local_buffer[256];

  //puts(prompt);
  printf("%s>", prompt);
  fflush(stdout);

  strcpy(local_buffer, buffer);

  printf("before buffer:%s",local_buffer);
  fflush(stdout);

  token = strtok(local_buffer, seps);  

  printf("It does not print this");
  fflush(stdout);  //Shouldn't this print the statement before?
  
  changePrompt();
}//Prompt

void changePrompt () {
  char *new_prompt = strtok(buffer,seps);   
  new_prompt = strtok(NULL, seps);
  
  if (new_prompt == NULL)
    strcpy(prompt,"\0");
  else  
    strcpy(prompt,new_prompt);  

  printf("%s",prompt);

}//changePrompt 
  #8  
Old 05-Apr-2004, 11:58
dsmith's Avatar
dsmith dsmith is offline
Senior Member
 
Join Date: Jan 2004
Location: Utah, USA
Posts: 1,351
dsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of light
I think your problem is: \r.

Add this charecter to your seps string, ala:
CPP / C++ / C Code:
char *seps = " \r\n";

It appears that your text file was created in windows, which adds the \r symbol. C is not particularly fond of this character.

The problem was occuring in your changePrompt function by the way. It may be that upon recieving the return charecter printf awaits for the newline charecter to print the line (otherwise it would overwrite the original line) until printing. Just a thought.

HTH,
d
  #9  
Old 05-Apr-2004, 12:35
nusstu nusstu is offline
New Member
 
Join Date: Mar 2004
Posts: 27
nusstu is on a distinguished road
Hi dsmith,

Thanks, I feel relieved now I thought nobody bothered reading my post since it was draggy.

Quote:
Originally Posted by dsmith
The problem was occuring in your changePrompt function by the way. It may be that upon recieving the return charecter printf awaits for the newline charecter to print the line (otherwise it would overwrite the original line) until printing. Just a thought.

hm..yes, I agree with you. Somehow, the printf() statement in changePrompt seems to be overwriting stdout for some bizarre reason upon reading /r. I think, the reason why it doesn't overwrite after it reads \n, is because stdout is flushed after newline. This makes me wonder also why is it fflush(stdout) doesn't flush stdout onto the screen?


P.S: I just started C a few weeks ago and already the future looks bleak.
  #10  
Old 05-Apr-2004, 14:36
dsmith's Avatar
dsmith dsmith is offline
Senior Member
 
Join Date: Jan 2004
Location: Utah, USA
Posts: 1,351
dsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of light
Quote:
Originally Posted by nusstu
This makes me wonder also why is it fflush(stdout) doesn't flush stdout onto the screen?
I have never had great luck with fflush on stdout. Maybe someone with some more background can give some insight. But when I want to print something to the screen immediately I use fprintf(stderr,...).

Quote:
P.S: I just started C a few weeks ago and already the future looks bleak.

I hope thats not true . I probably have as much of a love/hate relationship with C as anyone. But since I first learned it in 1986, I haven't found any other language that I can understand better or would rather use...
 
 

Recent GIDBlogAccepted for Ph.D. program by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Having trouble with Galaga-game DWk C Programming Language 49 17-Feb-2005 09:10
Can somebody look at this and point out any errors to me soulfly C Programming Language 7 31-Mar-2004 10:45
Dining Philosophers program Sam C Programming Language 9 19-Feb-2004 08:46

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 21:14.


vBulletin, Copyright © 2000 - 2009, Jelsoft Enterprises Ltd.