-2

I was trying to create a AVLtree using stdin input in C, the format I was trying to in put is: (7,19) (5,16) (9,13). The code I am using is

char str[1024];
     int key,value;
     while (fgets(str,256,stdin)!=NULL)//stop read files when reached end of the line
     {
        if(*str == "\n")
        {
            break;
        }
        if(sscanf(str,"(%d, %d)",&key, &value) == 2)// if the function can address both number
        {
            //InsertNode(AVLtree,key,value);
            printf("%d, %d\n", key,value);
        }
        else
        {
            printf("cannot get correct key & Value");
            exit(1)
        }

Basically, I am saying that read input from stdin using "fgets" function, in (%d, %d) format. Once it reached the end of the line, then stop. But by using this code, it only allows me to type in those nodes one per line, instead of typing all of them and end with enter. Is there any way to fix this?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
leo
  • 101
  • 6
  • 1
    `*str == "\n"` That's not how you compare strings. And this should have generated a warning. Read your warnings. – klutt Mar 30 '21 at 13:43
  • Hm... I think you are right Sir, I did changed it to str == NULL, but that doesn't work... – leo Mar 30 '21 at 13:47
  • read about `strcmp` – klutt Mar 30 '21 at 14:16
  • Errors belong on stderr: `fprintf(stderr, "cannot get correct key & Value");` – William Pursell Mar 30 '21 at 14:19
  • Thanks guys, I'll try with strcmp – leo Mar 30 '21 at 14:23
  • Hm... I changed from if(*str == "\n") to if strcmp(*str,"\n")==NULL), but it seems doesn't work as well... In the error section, it said that I am comparing between pointer and integer... – leo Mar 30 '21 at 14:26
  • You'll probably need to add `int offset;` and use `offset = 0; if (sscanf(str," (%d , %d )%n", &key, &value, &offset) == 2) { … }` — noting that `%n` 'conversions' don't get counted in the number of conversions, and noting the added spaces for format flexibility (see also [`sscanf()`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sscanf.html)). You can check that you got the closing parenthesis by ensuring `offset` is not 0 — which is why it was set before the call to `sscanf()`. See also the duplicate. – Jonathan Leffler Mar 30 '21 at 14:29
  • *"I changed from if(*str == "\n") to if strcmp(*str,"\n")==NULL)"* - Stop guessing. Read the documentation and find out how the functions are supposed to be used. – klutt Mar 30 '21 at 14:35
  • Given that you have `char str[1024];`, it would be more sensible to use `while (fgets(str, sizeof(str), stdin) != NULL)` for the loop control. Generally, use `sizeof` to specify the size of things when it is valid (and when it isn't — usually because the array is an argument to the function — pass the size explicitly and use that instead). – Jonathan Leffler Mar 30 '21 at 14:41
  • Of course you cannot compare the return value of strcmp to NULL since strcmp does not return a pointer. – klutt Mar 30 '21 at 14:41
  • @JonathanLeffler Thank you Sir, That was really helpfully! :) – leo Mar 30 '21 at 14:48

1 Answers1

1

As you don't know how many value pairs the user will enter you have to use a loop.

After a successful sscanf you can search for a closing parenthesis ')' and start the next sscanf from the position after it. To avoid an error message in case of additional spaces between or after the data I added code to skip whitespace and changed the format string to be more flexible. I use a function for skipping space and checki9ng for end-of-string because I need it at two places.

Edit:
As shown in the answer to a similar question How to use sscanf in loops? you can get the offset to the next position directly from sscanf using the %n format specifier, so the strchr is not necessary. I won't change this answer here. See the other question and adapt the code accordingly.

(There are more ways to solve this problem.)

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

/* skip whitespace and check for end of string */
int skip_space(char **pos)
{
    while(isspace(**pos))
    {
        (*pos)++;
    }
    return (**pos == '\0');
}

int main()
{
    char str[1024];
    char *pos;
    int key,value;
    printf("enter key-value pairs of integer numbers like (a,b)(c,d): ");
    while (fgets(str,sizeof(str),stdin)!=NULL)//stop read files when reached end of the line
    {
        pos = str;

        if(skip_space(&pos))
        {
            break;
        }

        do
        {
            /* added spaces to format string for more flexibility */
            if(sscanf(pos," (%d , %d )",&key, &value) == 2)// if the function can address both number
            {
                //InsertNode(AVLtree,key,value);
                printf("%d, %d\n", key,value);
            }
            else
            {
                printf("cannot get correct key & Value at position %d: %s\n", (int)(pos - str), pos);
                exit(1);
            } 
            /* since scanf was successful we must have a ')' in the input, so NULL should not occur */
            pos = strchr(pos, ')');
            /* skip ')' */
            pos++;
        } while(skip_space(&pos) == 0);
    }
    return 0;
}

Result:

enter key-value pairs of integer numbers like (a,b)(c,d): (1,2) ( 3 , 4 ) (5,6)(7.0,8)
1, 2
3, 4
5, 6
cannot get correct key & Value at position 21: (7.0,8)
enter key-value pairs of integer numbers like (a,b)(c,d): (1,2) ( 3 , 4 )  (5,6)                                                                                                            
1, 2                                                                                                                                                                                        
3, 4                                                                                                                                                                                        
5, 6                                                                                                                                                                                        
(7,8)                                                                                                                                                                                       
7, 8                                                                                                                                                                                        
                                                                                                                                                                                            
                                                                                                                                                                                            

Unrelated error: if(*str == "\n") is wrong.

If you want to check for a newline character at the beginning of the string, use

if(*str == '\n')

If you want to check if the whole string is equal to a string that consists of a single newline, use

if(strcmp(str, "\n") == 0)

or simplified

if(!strcmp(str, "\n"))
Bodo
  • 9,287
  • 1
  • 13
  • 29
  • Thank you Mr.Bodo! I'll try your way! I think you are right - I might need a loop for my input.. – leo Mar 30 '21 at 14:41