C - Get name from the string

Hello,

I have a question on how could I easily get name that is written on the beggining of a line in a file in C programming language not C++ or C#. Lets say I have a file test.txt and in it:

firsttext 2 4 2 2 2 -1 -99999
secondtext 3 3 13.4 3 3 3 3 3 3 3 5 5 10.2 7.3 -99999

I would like to get the name of a string in the beginning (firsttext or secondtext) of a line that has the most numbers that are 2% away from the value a user has written.

Lets say the user writes 2 and the program will return firsttext, if he writes 3 the program will return secondtext.

Thanks for your help in advance.
Read the whole line into a buffer (with fgets()).
Read the first string from the buffer (with sscanf()).

http://pubs.opengroup.org/onlinepubs/007908799/xsh/fgets.html
http://pubs.opengroup.org/onlinepubs/007908799/xsh/sscanf.html
Last edited on
Well if I do that i will only end up with the first word. I wont really solve the problem.
You could use strtok to split the string into its component parts.
http://www.cplusplus.com/reference/cstring/strtok/

To convert a string to a number, the function atof or strtod might be useful.
http://www.cplusplus.com/reference/cstdlib/atof/
http://www.cplusplus.com/reference/cstdlib/strtod/

(since strtod can also set a pointer to the first character after the number, it might be possible to apply it repeatedly to get all the numbers in the string).
I'm about as much of a newb when it comes to programming as is possible so take what I say with a grain of salt. But this can be solved with just math: write the function for standard deviation but substitute the input number in for the "average" in that equation. Calculate the deviation for each line and then pick the lower one.
Since i must read the text from file only once how would i save it to buffer and then call one line for example to get the first word and convert all the numbers into doubles? So i would have words seperated from numbers?
You could read a single line at a time, using fgets. Then process that line. The result of that processing will be two items, the name, and count of values meeting the requirements. Store those in a char string and an integer count.

Then read and process the next line. If the count is greater than the stored value, replace the stored values with the current values.

I would advise using a separate function to handle the detailed processing of each line.

After processing all the lines, the stored values should contain the required result.
And how can i jump to new line after I have read a space char or -99999. I have the following code:

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

int main (int argc, char *argv[]){
char* besede[10];
char tabela [99];
FILE *file = fopen("test.txt", "r" );
if (file == 0){
printf("Napaka!\n");
}
else{
char x;
int i = 0;
int j = 0;

//while(x = fgetc(file) != EOF){
while((x = fgetc(file)) != ' '){
tabela[i] = x;
printf("%c", x);
i++;
}

besede[j] = tabela;
x = 0;
j++;
//}
fclose(file);
/*for(int k = 0; k <= 10; k++){
printf("%s",besede[k]);
}*/
}
}
It would be easier based in your first post, to use fgets() to read a whole line at once, rather than reading a single character at a time.
http://www.cplusplus.com/reference/cstdio/fgets/

After that, split the string into words or 'tokens' using strtok()
http://www.cplusplus.com/reference/cstring/strtok/

Convert a character string into a number using atof()
http://www.cplusplus.com/reference/cstdlib/atof/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

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

    FILE *file = fopen("test.txt", "r" );

    if (file == 0)
    {
        printf("Napaka!\n");
        return 1;
    }

    while (fgets(linebuf, 1000, file))
    {
        /* printf("%s", linebuf); */

        char * pch;
        double num;
        printf ("Splitting string into tokens:\n");

        pch = strtok (linebuf, " ");
        if (pch != NULL)
        {
            printf("Name = %s\n", pch);
            pch = strtok (NULL, " ");
        }

        while (pch != NULL)
        {
            /* printf ("%s\n",pch); */

            num = atof(pch);
            printf("Number = %f\n", num);

            pch = strtok (NULL, " ");
        }

        printf("\n\n");
    }

    fclose(file);
    return 0;
}


Input:

firsttext 2 4 2 2 2 -1 -99999
secondtext 3 3 13.4 3 3 3 3 3 3 3 5 5 10.2 7.3 -99999


Output:

Splitting string into tokens:
Name = firsttext
Number = 2.000000
Number = 4.000000
Number = 2.000000
Number = 2.000000
Number = 2.000000
Number = -1.000000
Number = -99999.000000


Splitting string into tokens:
Name = secondtext
Number = 3.000000
Number = 3.000000
Number = 13.400000
Number = 3.000000
Number = 3.000000
Number = 3.000000
Number = 3.000000
Number = 3.000000
Number = 3.000000
Number = 3.000000
Number = 5.000000
Number = 5.000000
Number = 10.200000
Number = 7.300000
Number = -99999.000000
I did it a bit differently like this, but i have a problem why printf prints -99999 instead of firsttext and the same with secondtext. I already have the seconc part done I only have to figure out how to put the string into tabel if it is a word or if it is a number, then somehow transform char * stevila[1000] to double stevila[1000] :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char * argv[]) {
    char tabela[99];
    
    char * besede[1000];
    char * stevila[1000];
    
    int stevecBesed = 0;
    int stevecStevil = 0;
    
    
    FILE *f = fopen("test.txt","r");
    
    while(fscanf(f, "%s", &tabela) != EOF){
        
        if(atof(tabela) == NULL){
            besede[stevecBesed] = tabela;
            printf("%s ", besede[stevecBesed]);
            stevecBesed++;
        }
        else{
            stevila[stevecStevil] = tabela;
            stevecStevil++;
        }        
    }
    //printf("%s", besede[0]);
    
    fclose(f);
    return 0;
}
If anyone knows how to fix this. I need it quickly. Thank you.
The use of scanf seems a reasonable method.

But be careful when trying this if(atof(tabela) == NULL)
My compiler rejects this line as an error:
[Error] invalid operands to binary == (have 'double' and 'void *') 

Even if the compiler accepts it, if the input file contains any number which is zero, then atof(tabela) will result in zero, therefore this test cannot distinguish between a valid number "0" or some other text "abc".

i have a problem why printf prints -99999 instead of firsttext and the same with secondtext

Line 20 besede[stevecBesed] = tabela; is simply copying the address of tabela to the array. If the contents of tabela changes, so does the data pointed to by besede[stevecBesed].

That could be fixed like this, change the array definition to allocate space for the contents of the string
char besede[1000][20];

and use this to copy the string to the array:
strncpy(besede[stevecBesed], tabela, 20);


as for the numeric values,
double stevila[1000];

stevila[stevecStevil] = atof(tabela);
Last edited on
Thank you very mutch.
Oh one more thing. You mentioned the invalid operands to binary error. I didn't get it on my computer but got it on our schools online compiler. How do I fix that error?
Last edited on
A simple fix for the compiler error is to use this, put 0.0 instead of NULL
 
    if (atof(tabela) == 0.0)

However, if any of the numbers can be zero, there is still a logic error.

You could try to test whether or not the string contains a number, by checking for '0' to '9' or '-' as the first character.
So instead of this:
 
    if (atof(tabela) == 0.0)

you could try this:
 
if (!(tabela[0] >= '0' && tabela[0] <= '9') && tabela[0] != '-')

... though I don't like that very much :)
Last edited on
Topic archived. No new replies allowed.