I have file that will contain either two numbers with variable whitespace in between them or just a blank line. I need to know when the input is just a blank line, and then to not assign into those variables using fscanf.
Doing:
FILE *pFile = fopen (my_file, "r");
if (pFile == NULL) perror ("Error opening file");
int succ = 1, num1 = 0, num2 = 0;
while (succ != EOF)
{
succ = fscanf(pFile, "%d %d", &num1, &num2);
}
Works very well for detecting all of the numbers properly, but not the newline.
I tried:
fscanf(pFile, "%d %d %*[^\n]", &num1, &num2);
But it always properly assigns to both numbers. I want to be able to make a switch statement to do other logic based on if succ is 2 (indicating both numbers were assigned too) or 0 (indicating a blank line).
I'd prefer avoiding getline if possible; seems like that would be inefficient to use iostream stuff mixed with stdio functions.
I tried this guys suggestion, didn't work out, although logically I thought it would work, it didn't.
Honestly, I don't even understand why something like
"%d %d \n"
Wouldn't work. It's simple... scan the file until a newline, return back how many assignments were done, that's it!
"%d %d \n" will not work to achieve OP goals as any white-space directive consumes any white-space. Using ' ' or '\n' make no difference they both consume 0 or more white-spaces. (expect in '[]' specifiers)
OP wants to detect a '\n' and fscanf() is not a good choice. fgets() is better.
#define N (100 /* longest line */)
char buf[N];
while (fgets(buf, sizeof buf, pFile) != NULL) {
int cnt = sscanf("%d%d",&num1, &num2);
switch (cnt) {
case 0: Handle_NoNumbers(); break;
case 1: Handle_1Number(); break;
case 2: Handle_Success(); break;
}
}
The '%d' in fscanf(stream, "%d", &num) specifies to consume all leading white-space before a number without regard to '\n' or ' ', etc.
If code must use fscanf(), then code needs to consume leading white-space before calling fscanf(... "%d") in a way to distinguish '\n' from ' '.
// Consume white space except \n and EOF
int consume_ws(FILE *pFile) {
do {
int c = fgetc(pFile); // could use fscanf(...%c...) here
if (c == '\n' || c == EOF) return c;
} while (isspace(c));
ungetc(c, pFile); // put the char back
return 0;
}
...
while(1) {
int num[2];
int i;
for (i = 0; i < 2; i++) {
if (consume_ws(pFile)) {
Handle_ScantData(); // Not enough data
return;
}
if (1 != fscanf(pFile, "%d", &num[i]) {
Handle_NonnumericData();
return;
}
}
int ch = consume_ws(pFile);
if (ch == 0) Handle_ExtraData();
// Else do something with the 2 numbers
if (ch == EOF) return;
}
Related
So, I want to read some input in two integer variables with fscanf, the input must be
INTEGER ONE SPACE INTEGER \n
So for example a file could be like that:
235 190\n
And what I want to do is checking if there is any new line before the first integer or the second, then throw an exception if that's the case:
So basically what you do with fscanf for that case would be just to do like:
FILE *somefile;
[...]
int w, h;
if (fscanf(somefile, "%d%d") == EOF)
return (1);
But this method does not provide checking if there is a new line between the integers
(for example if there is INTEGER NEW_LINE INTEGER it will still read the second)
as it skips all spaces before seeing a digit, so what I managed to do is more close but still wrong:
FILE *somefile;
int w, h;
char check[2];
if (fscanf(somefile, "%d%c%d%c", &w, check, &h, check + 1) == EOF)
return (-1);
if (check[0] != ' ' || check[1] != '\n')
return (-1);
So after I did that I realized that the %c before the %d just reads one character, so if there is a space then a new line between the two, it will continue reading the file wrongly and won't detect an error.
Now I wonder if there is a way to skip all spaces like when using " %c", while knowing if we skipped a \n. Thanks for your help.
PS: I know we can use fgets and strtol but it would be too easy, in this project I can only use fscanf to parse the file.
scanf happily discards leading whitespace to match a %d conversion specifier, which makes this slightly difficult to do. But you can certainly use fgetc (or getchar) to validate a character and then push it back onto the stream for scanf to consume. Something like:
$ cat a.c
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
int c;
int d[2];
c = getchar();
if( 0
||!( c == '+' || c == '-' || isdigit(c))
|| ( c != ungetc(c, stdin) )
|| ( scanf("%d", d) != 1 )
|| ( getchar() != ' ' )
|| ( (c = getchar()) == EOF )
||!( c == '+' || c == '-' || isdigit(c))
|| ( c != ungetc(c, stdin) )
|| ( scanf("%d", d + 1) != 1 )
|| ( getchar() != '\n' )
){
fprintf(stderr, "invalid input!\n");
return EXIT_FAILURE;
}
printf("Read %d %d\n", d[0], d[1]);
return EXIT_SUCCESS;
}
$ gcc a.c
$ printf '5 28\n' | ./a.out
Read 5 28
$ printf '5 28\n' | ./a.out
invalid input!
$ printf ' 5 28\n' | ./a.out
invalid input!
$ printf ' 5 28' | ./a.out
invalid input!
if there is a way to skip all spaces
I can only use fscanf to parse the file.
Let us assume ungetc() is not allowed - which makes things harder.
"%d" happily consumes all (0 or more) leading white-spaces including '\n' without notice.
Use fscanf("%[...]") to find leading white-spaces first. The usual suspects are " \t\n\r\f\v".
// Consume leading whitespaces
// Return
// 1: \n or EOF found
// 0: not found
int EatLeadingWS(FILE *f) {
int count;
char space[2];
while ((count = fscanf("%1[ \t\n\r\f\v]", space)) == 1) {
if (space[0] == '\n') return 1;
}
return count == EOF;
}
Alternative: use "%c" and isspace(), but then we need a way to put non white-spaces back.
Then look for white-spaces before "%d"
int some_int;
if (EatLeadingWS(f) == 0) {
int count;
if ((count = fscanf("%d", &some_int)) == 1) {
printf("int %d found before a \\n\n", some_int);
}
}
Another alternative is to use char buf[100]; fscanf("%99[^\n]", buf) to read most of the line and then parse the string with sscanf(buf, "%d%1[ ]%d" ....
I am supposed to be "fixing" code given to me to make it display the correct number of visible characters in a file (spaces too). The correct number is supposed to be 977. I have never dealt with files before and I don't understand what I need to do to display the correct number.
* Driver Menu System for Homework
* Andrew Potter - Mar 5, 2019 <-- Please put your name/date here
*/
#include <stdio.h>//header file for input/output -
#include <stdlib.h>
#include <ctype.h>
// since you will place all your assigned functions (programs) in this file, you do not need to include stdio.h again!
int menu(void); //prototype definition section
void hello(void);
void countall(void);
int main(void)
{
int selection = menu();
while(selection != 99) {
switch(selection) {
case 1:
hello();
break;
case 2:
countall();
break;
case 3:
break;
case 4:
break;
default:
printf("Please enter a valid selection.\n");
}
selection = menu();
}
return 0;
}
int menu(void) {
int choice;
printf("***************************\n");
printf(" 1. Hello \n");
printf(" 2. Countall\n");
printf(" 3. \n");
printf(" 4. \n");
printf("99. Exit\n");
printf("Please select number and press enter:\n");
printf("***************************\n");
scanf("%d", &choice);
getchar();
return choice;
}
void hello(void) {
printf("Hello, World!!!\n");
}
//*****Andrew 5/1/19*****
#define SLEN 81 /* from reverse.c */
/* original header: int count(argc, *argv[]) */
void countall(void)
{
int ch; // place to store each character as read
FILE *fp; // "file pointer"
long unsigned count = 0;
char file[SLEN]; /* from reverse.c */
/*Checks whether a file name was included when run from the command prompt
* The argument count includes the program file name. A count of 2 indicates
* that an additional parameter was passed
if (argc != 2)
{
printf("Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
* The following uses the second parameter as the file name
* and attempts to open the file
if ((fp = fopen(argv[1], "r")) == NULL)
{
printf("Can't open %s\n", argv[1]);
exit(EXIT_FAILURE);
} */
/*************************************
Code from reverse.c included to make the program work from within our IDE
*************************************/
puts("Enter the name of the file to be processed:");
scanf("%s", file);
if ((fp = fopen(file,"rb")) == NULL) /* read mode */
{
printf("count program can't open %s\n", file);
exit(EXIT_FAILURE);
}
/* EOF reached when C realizes it tried to reach beyond the end of the file! */
/* This is good design - see page 573 */
while ((ch = getc(fp)) != EOF)
{
if (isprint(ch)) {
count++;
}
else if (isprint(ch)) {
count++;
}
putc(ch,stdout); // same as putchar(ch);
count++;
}
fclose(fp);
printf("\nFile %s has %lu characters\n", file, count);
}
I expected I would get the correct number of visible characters using the combination of isprint and isspace but I usually get 2086.
The assignment directions are: "Word identifies 977 characters including spaces. Your current countall() believes there are 1043. Make the corrections necessary to your code to count only the visible characters and spaces! (Hint: check out 567 in your textbook.)" Before I edited any code the count was 1043, now i am getting 2020. I need 977.
isprint() returns a Boolean result - zero if the character is not "printable", and non-zero if it is. As such isprint(ch) != '\n'makes no sense. Your complete expression in the question makes even less sense, but I'll come on to that at the end.
isprint() on its own returns true (non-zero) for all printable characters, so you need no other tests. Moreover you increment count unconditionally and in every conditional block, so you are counting every character and some twice.
You just need:
if( isprint(ch) )
{
count++;
}
putc( ch, stdout ) ;
While your code is clearly an incomplete fragment, it is not clear where or how your are reading ch. You need a getc() or equivalent in there somewhare.
while( (ch = getc(fp)) != EOF )
{
if( isprint(ch) )
{
count++;
}
putc( ch, stdout ) ;
}
It is not clear whether you need to count all whitespace (including space, tab and newline) or just "spaces" as you stated. If so be clear that isprint() will match space, but not control characters newline or tab. isspace() matches all these, but should not be counted separately to isprint() because 'space' is in both white-space and printable sets. If newline and tab are to be counted (and less likely; "vertical tab") then:
while( (ch = getc(fp)) != EOF )
{
if( isprint(ch) || isspace(ch) )
{
count++;
}
putc( ch, stdout ) ;
}
Another aspect of C that you seem to misunderstand is how Boolean expressions work. To test a single variable for multiple values you must write:
if( var == x || var == y || var == z )
You have written:
if( var == x || y || z )
which may make sense in English (or other natural language) when you read it out aloud, but in C it means:
if( var == (x || y || z ) )
evaluating (x || y || z ) as either true or false and comparing it to var.
It is probably worth considering the semantics of your existing solution to show why it actually compiles, but produces the erroneous result it does.
Firstly,
isprint(ch) != '\n' || '\t' || '\0'
is equivalent to isprint(ch) != true, for the reasons described earlier. So you increment the counter for all characters that are not printable.
Then here:
isspace(ch) == NULL
NULL is a macro representing an invalid pointer, and isspace() does not return a pointer. However NULL will implicitly cast to zero (or false). So here you increment the counter for all printable characters that are not spaces.
Finally, you unconditionally count every character here:
putc(ch,stdout); // same as putchar(ch);
count++;
So your result will be:
number-of-non-printing-characters +
number-of-printing-characters - number-of-spaces +
total-number-of-characters
which is I think (2 x file-length) - number-of-spaces
Finally note that if you open a text file that has CR+LF line ends (conventional for text files on Windows) in "binary" mode, isspace() will count two characters for every new-line. Be sure to open in "text" mode (regardless of the platform).
From isprint():
A printable character is a character that occupies a printing position on a display (this is the opposite of a control character, checked with iscntrl).
and
A value different from zero (i.e., true) if indeed c is a printable character. Zero (i.e., false) otherwise.
So that function should be sufficient. Please note that you have to make sure to feed all these is...() functions from <ctype.h> unsigned values. So if you use it with a value of uncertain origin, better cast to char unsigned.
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char const *filename = "test.txt";
FILE *input = fopen(filename, "r");
if (!input) {
fprintf(stderr, "Couldn't open \"%s\" for reading. :(\n\n", filename);
return EXIT_FAILURE;
}
long long unsigned count = 0;
for (int ch; (ch = fgetc(input)) != EOF;) {
if (isprint(ch))
++count;
}
fclose(input);
printf("Count: %llu\n\n", count);
}
If I wasn't lucky enough to guess which characters you want to be counted, have a look at ctype.h, there is a table.
if ((ch == '\t') || isprint(ch))
count++;
If you want to handle tabs differently (maybe to count how many spaces they use):
if (ch == '\t') {
/* Do smth */
} else if (isprint(ch)) {
count++;
}
This should be enough.
I have a matrix G in MATLAB that I have printed into a text file using:
file = fopen('G.dat','w');
fprintf(file, [repmat('%f\t', 1, size(G, 2)) '\n'], G');
fclose(file);
The dimension of this matrix is 100 x 500. If I count rows and columns using awk, for instance, using
cat G.dat | awk '{print NF}END{print NR}'
I see that the dimensions correspond to the original one.
Now, I want to read this file, G.dat, from a C program that counts the columns of the first row just to understand the columns' dimension as in:
while (!feof(file) && (fscanf(file, "%lf%c", &k, &c) == 2) ) {
Ng++;
if (c == '\n')
break;
}
Unfortunately it gives me Ng = 50000 and it doesn't recognize any of the '\n'.
Instead, if I create the text file just by copying and pasting the data, it works. Can you explain me why? Thanks!
Are you working in Windows? Try opening your output file in text mode:
file = fopen('G.dat','wt');
This will automatically insert a carriage return before each newline when writing to the file.
Code's approach is too fragile to "counts the columns of the first row just to understand the columns' dimension". fscanf(file, "%lf%c"... is too susceptible to variant white-space delimiters and EOL to detect the '\n'.
Recommend explicitly examine white-space to determine width:
// return 0 on success, 1 on error
int GetWidth(FILE *file, size_t *width) {
*width = 0;
for (;;) {
int ch;
while (isspace(ch = fgetc(file))) {
if (ch == '\n') return 0;
}
if (ch == EOF) return 0;
ungetc(ch, file);
double d;
if (fscanf(file, "%lf", &d) != 1)) {
return 1; // unexpected non convertible text
}
(*width)++;
}
}
//Sample, usage
size_t width;
if (GetWidth(file, &width)) return 1;
// read entire file
rewind(file);
for (size_t line = 0; foo(); line++)
for (size_t column = 0; column<width; column++) {
double d;
if (fscanf(file, "%lf", &d) != 1)) {
break; // EOF, unexpected non convertible text or input error
}
}
...
}
Matlab writes rows as
%f\t%\f .. %f\t\n
which is a problem. I have used
dlmwrite('G.dat', G, '\t');
and it is fine!
if I understand the matlab syntax correctly, this expands to a format string like %f\t%f\t%f\t\n\%f\t%f\t%f\t\n for a 3x2 matrix. Note the extra \t at the end of each line. If this assumption is correct, the last fscanf() call in a line will assign the last \t to &c. The next fscanf() call just skips the \n because it doesn't match your format.
I'd propose you use fgets() instead for reading each line and then loop over the fields using strtok(), reading the values with atof() e.g.
char buf[8192];
if (fgets(buf, 8192, file))
{
if (strtok(buf, '\t'))
{
++Ng;
while (strtok(0, '\t')) ++Ng;
}
}
else
{
/* error reading ... */
}
If I input 5 5 at the terminal, press enter, and press enter again, I want to exit out of the loop.
int readCoefficents(double complex *c){
int i = 0;
double real;
double img;
while(scanf("%f %f", &real, &img) == 2)
c[i++] = real + img * I;
c[i++] = 1 + 0*I; // most significant coefficient is assumed to be 1
return i;
}
Obviously, that code isn't doing the job for me (and yes, I know there is a buffer overflow waiting to happen).
scanf won't quit unless I type in a letter (or some non-numeric, not whitespace string). How do I get scanf to quit after reading an empty line?
Use fgets to read console input:
int res = 2;
while (res == 2) {
char buf[100];
fgets(buf, sizeof(buf), stdin);
res = sscanf(buf, "%f %f", &real, &img);
if (res == 2)
c[i++] = real + img * I;
}
c[i++] = 1 + 0*I; // most significant coefficient is assumed to be 1
return i;
The specific problem you're having is that a scanf format string of %f will skip white space (including newlines) until it finds an actual character to scan. From the c99 standard:
A conversion specification is executed in the following steps:
- Input white-space characters (as specified by the isspace function) are skipped, unless the specification includes a '[', 'c', or 'n' specifier.
and, elsewhere, describing isspace():
The standard white-space characters are the following: space ' ', form feed '\f', new-line '\n', carriage return '\r', horizontal tab '\t', and vertical tab '\v'.
Your best bet is to use fgets to get the line (and this can be protected from buffer overflow very easily), then use sscanf on the resultant line.
The scanf function is one of those ones you should look at very warily. The following piece of code is one I often use to handle line input:
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
// Test program for getLine().
int main (void) {
int rc;
char buff[10];
rc = getLine ("Enter string> ", buff, sizeof(buff));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", buff);
return 1;
}
printf ("OK [%s]\n", buff);
return 0;
}
Testing it with various combinations:
pax> ./prog
Enter string>[CTRL-D]
No input
pax> ./prog
Enter string> a
OK [a]
pax> ./prog
Enter string> hello
OK [hello]
pax> ./prog
Enter string> hello there
Input too long [hello the]
pax> ./prog
Enter string> i am pax
OK [i am pax]
What I would do is to use this function to get a line safely, then simply use:
sscanf (buffer, "%f %f", &real, &img)
to get the actual values (and check the count).
In fact, here's a complete program which is closer to what you want:
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
int main (void) {
int i = 1, rc;
char prompt[50], buff[50];
float real, imag;
while (1) {
sprintf (prompt, "\nEnter real and imaginary for #%3d: ", i);
rc = getLine (prompt, buff, sizeof(buff));
if (rc == NO_INPUT) break;
if (*buff == '\0') break;
if (rc == TOO_LONG) {
printf ("** Input too long [%s]...\n", buff);
}
if (sscanf (buff, "%f %f", &real, &imag) == 2) {
printf ("Values were %f and %f\n", real, imag);
i++;
} else {
printf ("** Invalid input [%s]\n", buff);
}
}
return 0;
}
along with a test run:
pax> ./testprog
Enter real and imaginary for # 1: hello
** Invalid input [hello]
Enter real and imaginary for # 1: hello there
** Invalid input [hello there]
Enter real and imaginary for # 1: 1
** Invalid input [1]
Enter real and imaginary for # 1: 1.23 4.56
Values were 1.230000 and 4.560000
Enter real and imaginary for # 2:
pax> _
There's a way to do what you want using just scanf:
int readCoefficents(double complex *c) {
int i = 0;
double real;
double img;
char buf[2];
while (scanf("%1[\n]", buf) == 0) { // loop until a blank line or EOF
if (scanf("%lf %lf", &real, &img) == 2) // read two floats
c[i++] = real + img * I;
scanf("%*[^\n]"); // skip the rest of the line
scanf("%*1[\n]"); // and the newline
}
c[i++] = 1 + 0*I; // most significant coefficient is assumed to be 1
return i;
}
If the user only enters 1 float on a line, it will read the next line for the second value. If any random garbage is entered, it will skip up to a newline and try again with the next line. Otherwise, it will just go on reading pairs of float values until the user enters a blank line or an EOF is reached.
re PAXDIABLO solution: it does not work properly with EMPTY line entered by user, so this line shall be added in your getLine() function
if (strlen(buff) <= 1) return NO_INPUT;
after the line:
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
So it will become :
...
if (strlen(buff) <= 1) return NO_INPUT;
if (fgets (buff, sz, stdin) == NULL) return NO_INPUT;
....
Instead of
while(scanf("%f %f", &real, &img) == 2)
try
while(scanf("%f %f%*c", &real, &img) == 2)
scanf("%f%*c", &myfloat); // will read a float and all eventual characters after it
EDIT:
complete code with main is here http://codepad.org/79aLzj2H
and once again this is were the weird behavious is happening
for (i = 0; i<tab_size; i++)
{
//CORRECT OUTPUT
printf("%s\n", tableau[i].capitale);
printf("%s\n", tableau[i].pays);
printf("%s\n", tableau[i].commentaire);
//WRONG OUTPUT
//printf("%s --- %s --- %s |\n", tableau[i].capitale, tableau[i].pays, tableau[i].commentaire);
}
I have an array of the following strcuture
struct T_info
{
char capitale[255];
char pays[255];
char commentaire[255];
};
struct T_info *tableau;
This is how the array is populated
int advance(FILE *f)
{
char c;
c = getc(f);
if(c == '\n')
return 0;
while(c != EOF && (c == ' ' || c == '\t'))
{
c = getc(f);
}
return fseek(f, -1, SEEK_CUR);
}
int get_word(FILE *f, char * buffer)
{
char c;
int count = 0;
int space = 0;
while((c = getc(f)) != EOF)
{
if (c == '\n')
{
buffer[count] = '\0';
return -2;
}
if ((c == ' ' || c == '\t') && space < 1)
{
buffer[count] = c;
count ++;
space++;
}
else
{
if (c != ' ' && c != '\t')
{
buffer[count] = c;
count ++;
space = 0;
}
else /* more than one space*/
{
advance(f);
break;
}
}
}
buffer[count] = '\0';
if(c == EOF)
return -1;
return count;
}
void fill_table(FILE *f,struct T_info *tab)
{
int line = 0, column = 0;
fseek(f, 0, SEEK_SET);
char buffer[MAX_LINE];
char c;
int res;
int i = 0;
while((res = get_word(f, buffer)) != -999)
{
switch(column)
{
case 0:
strcpy(tab[line].capitale, buffer);
column++;
break;
case 1:
strcpy(tab[line].pays, buffer);
column++;
break;
default:
strcpy(tab[line].commentaire, buffer);
column++;
break;
}
/*if I printf each one alone here, everything works ok*/
//last word in line
if (res == -2)
{
if (column == 2)
{
strcpy(tab[line].commentaire, " ");
}
//wrong output here
printf("%s -- %s -- %s\n", tab[line].capitale, tab[line].pays, tab[line].commentaire);
column = 0;
line++;
continue;
}
column = column % 3;
if (column == 0)
{
line++;
}
/*EOF reached*/
if(res == -1)
return;
}
return ;
}
Edit :
trying this
printf("%s -- ", tab[line].capitale);
printf("%s --", tab[line].pays);
printf("%s --\n", tab[line].commentaire);
gives me as result
-- --abi -- Emirats arabes unis
I expect to get
Abu Dhabi -- Emirats arabes unis --
Am I missing something?
Does printf have side effects?
Well, it prints to the screen. That's a side effect. Other than that: no.
is printf changing its parameters
No
I get wrong resutts [...] what is going on?
If by wrong results you mean that the output does not appear when it should, this is probably just a line buffering issue (your second version does not print newline which may cause the output to not be flushed).
It's highly unlikely that printf is your problem. What is far, far more likely is that you're corrupting memory and your strange results from printf are just a symptom.
There are several places I see in your code which might result in reading or writing past the end of an array. It's hard to say which of them might be causing you problems without seeing your input, but here are a few that I noticed:
get_lines_count won't count the last line if it doesn't end in a newline, but your other methods will process that line
advance will skip over a newline if it is preceded by spaces, which will cause your column-based processing to get off, and could result in some of your strings being uninitialized
get_word doesn't do any bounds checks on buffer
There may be others, those were just the ones that popped out at me.
I tested your code, adding the missing parts (MAX_LINE constant, main function and a sample datafile with three columns separated by 2+ whitespace), and the code works as expected.
Perhaps the code you posted is still not complete (fill_table() looks for a -999 magic number from get_word(), but get_word() never returns that), your main function is missing, so we don't know if you are properly allocating memory, etc.
Unrelated but important: it is not recommended (and also not portable) to do relative movements with fseek in text files. You probably want to use ungetc instead in this case. If you really want to move the file pointer while reading a text stream, you should use fgetpos and fsetpos.
Your approach for getting help is very wrong. You assumed that printf had side effects without even understanding your code. The problem is clearly not in printf, but you held information unnecessarily. Your code is not complete. You should create a reduced testcase that compiles and displays your problem clearly, and include it in full in your question. Don't blame random library functions if you don't understand what is really wrong with your program. The problem can be anywhere.
From your comments, i am assuming if you use these printf statements,
printf("%s\n", tableau[i].capitale);
printf("%s", tableau[i].pays);
printf("%s\n", tableau[i].commentaire);
then everything works fine...
So try replacing your single printf statement with this. (Line no. 173 in http://codepad.org/79aLzj2H)
printf("%s\n %s %s /n", tableau[i].capitale, tableau[i].pays, tableau[i].commentaire);