0

I have the following file:

username=teste1;
status=ONLINE;
username=teste2;
status=ONLINE;
username=teste3;
status=OFFLINE;

Where one of the lines represents the user name and the bottom line represents the user's status just like above.

I would like to search for a specific username and show its status. But I can't seem to get the right return.

For now I have the following code:

int isUserOnline(char *username) {

    FILE *f;

    f = fopen(FILE_NAME,"r");
    int i = 0;

    char line[MAX] = {'\0'};
    char destiny[MAX] = {'\0'};
    while(!feof(f)) {

        bzero(destiny, sizeof(destiny));

        fgets(line, sizeof(line), f);
        valueAfterEquals(destiny, line);
        if(strcmp(destiny, username)) {
            bzero(destiny, sizeof(destiny));
            fgets(line, sizeof(line), f);
            valueAfterEquals(destiny, line);
            printf("is: %s \n", destiny);
            if(strcmp(destiny, "OFFLINE")) {
                return 1;
            }
            else 
                return 0;
        }
    }
}

The code above should look for the username and check if it exists, if it is offline, return one;

The valueAfterEquals function is, just takes the value after the equal sign and assigns it to a string:

void valueAfterEquals(char * destiny, char * buffer){

    int k = 0;
    while(buffer[k] != '='){ 
        k++;
    }

    int i = 0;
    k++; //pular o '='
    while(buffer[k] != ';'){
        destiny[i] = buffer[k]; 
        k++;
        i++;
    }
}
Zerothis
  • 9
  • 1
  • 1
  • 5
  • 1
    What isn't working? Are you getting an error? You're not closing the file you've opened, and you aren't returning a value in all cases from the function. Consider what happens if the while loop is never entered or if the name is never found. – Retired Ninja May 19 '21 at 02:16
  • When I pass the teste3 argument, i get a ONLINE response, and it should be OFFLINE. The file is being opened normally, it's just that FILE_NAME value is the .txt file. – Zerothis May 19 '21 at 02:19
  • 2
    See [`while (!feof(file))` is always wrong](https://stackoverflow.com/q/5431941/15168). You should also explicitly check the return value from each call to `fgets()` and process failure appropriately. Ignoring the return value is a bad idea. – Jonathan Leffler May 19 '21 at 02:20
  • 2
    The problem you are describing seems to be in the code you have not shown. Consider making a [mcve]. – Retired Ninja May 19 '21 at 02:21
  • You should also choose whether you're learning C or C++ — the idiomatic answers for the two very different languages are quite different. – Jonathan Leffler May 19 '21 at 02:22
  • Hey, Jonathan. Either way, the file is getting looped. So even if a change it, it continues to give the error. – Zerothis May 19 '21 at 02:22
  • Actually the problem is in the userIsOnline function. It doesnt return me the return answer – Zerothis May 19 '21 at 02:23
  • In `valueAfterEquals()` add `buffer[k] = 0;` as the last line to nul-terminate `destiny`. If you are using C++, using `std::string` and `.rfind()` makes locating the `'='` trivial. If not, remove the `[c++]` tag from your question. C and C++ are vastly different languages today. – David C. Rankin May 19 '21 at 02:28
  • I've just removed the c++ tag! I'll add it, but this function is working fine! – Zerothis May 19 '21 at 02:34

1 Answers1

1

I suggest using fscanf or sscanf. Consider the following example:

char exampleStr[] = "username=teste1;";
char username[64];
// TO DO: add error checking on sscanf
sscanf(exampleStr, "%*[^=]=%[^;]", username); // username now holds "teste1"
if (strcmp(username, targetUsername) == 0)
{
    // usernames are equal, do whatever you want
}
KleberPF
  • 120
  • 1
  • 7
  • Nice! But how can I read the next line in this way? Like, when I find the user, can I loop one more time and take the value below (status = ONLINE)? Thanks! – Zerothis May 19 '21 at 02:29
  • Sure, just use `fgets`. When you find the username, read one more line through `fgets`, get the status and stop the loop. – KleberPF May 19 '21 at 02:31
  • 1
    `fgets()` with `sscanf()` provides a very good solution. Though you could simply use `"%s=%[^;]"` as the format string and separate the key and value automatically. (don't forget the *field-width* modifier to protect your array bounds). (if using `sscanf()` there is no need for `strcspn()`...) – David C. Rankin May 19 '21 at 02:31
  • Forgot to mention, but be careful with the trailing new line from `fgets`. You can remove it the same way I removed the `;`. – KleberPF May 19 '21 at 02:33
  • @DavidC.Rankin I believe your format string doesn't work. The `%s` will get the entire string. You should use something like `%[^=]=%[^;]`. But indeed, this is better than using `strcspn`. I will edit my answer. – KleberPF May 19 '21 at 02:40
  • Yes, you are correct. `%[^=]=%[^;]` will work fine. Don't forget the *field-width* modifier of `max - 1` on each conversion specifier. – David C. Rankin May 19 '21 at 02:56
  • So exampleStr, should hold the value of each line of the file, in order to compare? – Zerothis May 19 '21 at 03:07
  • @VictorSoldera if you use `fgets`, you will get the entire line (with a `\n` at the end). `exampleStr` was an example of a possible line without the newline at the end. – KleberPF May 19 '21 at 03:08
  • I'm a little bugged. If a use fgets() won't I get the full file? Like, im looping through the whole file, and verifying if the user exists, if the user exists, then I fgets, and it keeps sending me the whole file. Thanks a lot for your help, this file part is bugging me haha – Zerothis May 19 '21 at 03:21
  • @VictorSoldera `fgets` reads a line, not the full file. Conveniently, `fgets` returns a NULL pointer if the end of the file was reached (or a reading error occurred). So you can loop and check the return value of `fgets` each time, and when it's NULL you reached the end. – KleberPF May 19 '21 at 03:24
  • It worked! Thank you Kleber and David for your time! – Zerothis May 19 '21 at 21:06