0

It's a relatively simple thing to do, but I've been having problems separating a string from a file into multiple variables. I've tried strtok and sscanf with delimiters, but I seem to be doing something wrong.

#define MAX 40
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

int main()
{
    char brd_str[26];
    char board[26], Res[26], Ind[26], Cap[26];
    int i=0, n=0;
    FILE *data;

    data = fopen ("C:\\datafile.txt", "rt");
    fgets(brd_str, 26, data);
    sscanf(brd_str,"%d[^,],%f[^,],%e[^,],%e[^,]", &board, &Res, &Ind, &Cap);
    printf("%3d %6d %8e %8e", board, Res, Ind, Cap);

    fclose(data);
    printf("\nPlease enter something for the program to exit");
    scanf("%d", &i);
    return(0);
}

The string itself looks like this 2,4.57,2.01e-2,5.00e-8. The comma would be the delimiter in this case. When I compile it I have really large numbers which are incorrect.

This would have to be done multiple times (up to 40), and the variables themselves will be used for calculations.

There seems to be something wrong with the sscanf statement I've put in. I'm not really sure what the problem is.

  • 2
    It might help you debug the code if you were to print out 'brd_str' right after fgets(). Perhaps it's content will not be what you expect? – Mahonri Moriancumer Apr 24 '14 at 15:11
  • I've just tried it, and it seems to be displaying the string as it is on the file. – user3569350 Apr 24 '14 at 15:13
  • So 'board' is a character string. It appears that you are attempting to sscanf() it with a %d? Perhaps you should sscanf it with %s, and later print it with %s? – Mahonri Moriancumer Apr 24 '14 at 15:14
  • You may not combine a scanset `"%[...]"` with another format-specifier like `"%s"` like that. s, d, f, [...]... They all are distinct, combinations aren't valid. – Utkan Gezer Apr 24 '14 at 15:15

5 Answers5

0

Basically, your most immediate problem is

char board[26], Res[26], Ind[26], Cap[26];

So, you have strings ...

sscanf(brd_str,"%d[^,],%f[^,],%e[^,],%e[^,]", &board, &Res, &Ind, &Cap);

you can't read with "%e" into (addresses of) strings!

printf("%3d %6d %8e %8e", board, Res, Ind, Cap);

you can't print strings with "%e"


Also there are quite a few more problems with your code.

pmg
  • 106,608
  • 13
  • 126
  • 198
0

Change:

    char board[26], Res[26], Ind[26], Cap[26];

to:

   int board;
   float Res;
   float Ind;
   float Cap; 

And, change:

printf("%3d %6d %8e %8e", board, Res, Ind, Cap);

to (perhaps):

printf("%3d %6f %8e %8e", board, Res, Ind, Cap);
Mahonri Moriancumer
  • 5,993
  • 2
  • 18
  • 28
0

Just for a hint at coding style, take a look at the following code...

#include <stdio.h>
#include <stdlib.h>

int main( int argc, char **argv )
{
FILE *file;
int c, cp;
char *buf = (char*)malloc( sizeof( char ) * 100 );

for (c = 0; c < 100; c++ )
{
    buf[c] = 0;
}

file = fopen( "input.txt", "r" );

cp = 0;
while( ( c = fgetc( file ) ) != EOF )
{
    if ( c != ',' )
    {
        buf[cp] = (int)c;
        cp++;
    }
    printf( "%c", c );
}

for (c = 0; c < 100; c++ )
{
    printf( "Buf%d: %c\n", c, buf[c] );
}

free( buf );

return 0;
}

This code loads characters in from file. If you are wanting strings, consider simply that strings are arrays of characters... There are quite a few examples online you can look at including the following...

Read .CSV file in C

I hope this helps...

Community
  • 1
  • 1
Rich Pickering
  • 237
  • 2
  • 6
0

You may not combine a scanset format-specifier with other types of format-specifiers like that. Just like you may not have "%df" as a format-specifier for integer float (???), or "%si" for string integer (???), you may not have things like "%d[^,]".

"%d" alone would already abort reading when it encounters a ',' or any other non-digit character, so what you are trying to do there is extra and invalid precaution. Having that "[^,]" next to it, will cause sscanf to look for a '[' then '^' then ',' then ']' inside that string.

So, in short, you should rather be having something rather simple like the following:

#include<stdio.h>

int main( ){

    int board;
    float Res, Ind, Cap;

    scanf( "%d,%f,%e,%e", &board, &Res, &Ind, &Cap );
    // reads digit sequence until the non-digit input
    // reads that number into board as an integer
    // consumes a comma character
    // and so on...

    printf( "%d\n%f\n%e\n%e", board, Res, Ind, Cap );

    return 0;
}
Utkan Gezer
  • 3,009
  • 2
  • 16
  • 29
0

Addressing only:
...I've tried strtok ... but I seem to be doing something wrong....
And
This would have to be done multiple times (up to 40)

It sounds like you have an input file with a variable number of inputs, up to 40?
So the way the data is read should accommodate, and stop reading at end of data.

Here is an example doing these things using strtok():

With a file containing these values:

1.2,345,23,78,234,21.4567,2.45566,23,45,78,12,34,5.678    

I also verified it works with exponential notation, such as:

1.2,345,23,7.8e3,2.34e-2,21.4567,2.45e-8,2.3e3,45,78,12,34,5.678

And using this code, strtok will parse through using ", \n" as delimiters:

#include <ansi_c.h>

int main(void)
{
    FILE *fp;
    char *tok;
    double numbers[100];
    char tempBuf[260], lineBuf[260];
    int i=0;

    memset(numbers, 0, sizeof(numbers)/sizeof(numbers[0])*sizeof(int));
    fp = fopen("F:\\play3\\numbers.txt", "r");
    while(fgets (lineBuf, sizeof(lineBuf), fp))
    {
        tok = strtok(lineBuf, ", \n");
        while(tok)
        {
            strcpy(tempBuf, tok);
            if(strlen(tempBuf)>0)
            {
                numbers[i++] = strtod(tempBuf, NULL);
            }
            tok = strtok(NULL, ", \n");

        }
    }
    fclose(fp);
    return 0;
}  

With the following results:
enter image description here

ryyker
  • 22,849
  • 3
  • 43
  • 87