0

what I'm trying to do is create a loop that collects a string (in this case a name) and then questions the user through the request of a character whether he wants to keep inserting more.

#include <stdio.h>
#include <string.h>
void main(){
    char c, str[5][20];
    int i=0;
    do {
        printf("What's your name?\n");
        gets(str[i]);
        i++;
        printf("Do you want to insert more?\n");
        scanf("%c\n",&c);
    } while (c=='y');
}

The number of strings that I read and their lenght are arbitrary and not what I'm having trouble with, was just wondering if there was a "correct way" of using this kind of acquisition or if I should give up on it.

melpomene
  • 84,125
  • 8
  • 85
  • 148
Simone
  • 33
  • 5
  • Please describe the current behaviour of your program, including what wrong/missing behaviour it has. But yes, it's definitely possible to do what you want. The general approach is to pick a MAX_LENGTH for each string and use dynamic memory allocation for each name. – kaylum Jan 02 '17 at 21:26
  • 1
    Please don't use `gets`. It is prone to many issues including security. Try using `fgets` instead. – MateoConLechuga Jan 02 '17 at 21:27
  • What exactly is your question? – melpomene Jan 02 '17 at 21:30
  • `main` should return `int`, not `void`. – melpomene Jan 02 '17 at 21:30
  • I don't recommend using `scanf` for user input. – melpomene Jan 02 '17 at 21:30
  • the problem I'm having right now is that it's really not consistent. I'll run the program, put my name in (press enter), write y (press enter) and plenty of times the program won't show the demand for a name but just wait for a new input. – Simone Jan 02 '17 at 21:39
  • 1
    That should happen every single time, because that's what you told `scanf` to do: Every whitespace character in the format string (such as your `'\n'`) makes `scanf` read and skip over all whitespace in the input. As long as you keep hitting enter, `scanf` won't return. (This is why I recommend against `scanf` for user input.) – melpomene Jan 02 '17 at 21:43
  • What would you suggest using then? I tried using c=getc() but it gave me even less consistent results hence I returned to the scanf. Also excuse my ignorance but is it always better to call main as an int? I used void since it doesn't need to communicate any number. – Simone Jan 02 '17 at 21:47
  • 1
    Do all user input through `fgets`, reading a whole line at a time, which you can then analyze afterwards (either manually or with `strtol`, `sscanf`, etc.). – melpomene Jan 02 '17 at 21:48
  • I'm not familiar with fgets but from what I understand it will take a fixated amount of characters (its second argument), how do the other functions you talked about help moderating it? – Simone Jan 02 '17 at 21:57
  • 1
    `main` does need to communicate a number to its caller, namely the exit status of the program. Use `0` or `EXIT_SUCCESS` to signal success, `EXIT_FAILURE` for error (the latter two require `#include `). Not all platforms use this, but on those that do, you need to return something because the (system specific) startup code can't magically know you declared `main` as `void`; it'll try to use the non-existent return value anyway. (See also http://c-faq.com/ansi/maindecl.html, http://c-faq.com/ansi/voidmainexamp.html.) – melpomene Jan 02 '17 at 21:57
  • The second argument to `fgets` is the size of the buffer you're storing the input in. For "quick and dirty" programs (and homework), you usually just declare an array that's "big enough" (e.g. `char line[200];`); if you want to get fancier, you have to deal with dynamic memory allocation. – melpomene Jan 02 '17 at 22:03
  • Thanks, you're very knowledgeable. Does fgets stop at an enter prompt like a normal gets does then? And what practical uses do strtol and sscanf have? – Simone Jan 02 '17 at 22:08
  • `fgets` is the "normal" read-one-line function. `gets` isn't normal: It works like `fgets` but it doesn't limit the input. If the user enters more characters than fit into your variable, unpredictable things happen (e.g. crashing your program, corrupting other variables, ...). `strtol` can convert a string such as `"123"` into its (long) integer value `123`. `sscanf` is like `scanf` but instead of reading from `stdin` it reads from a string you pass in: `int x; sscanf("-42", "%d", &x);` would set `x` to `-42`. – melpomene Jan 02 '17 at 22:15
  • Again thank you very much, good night! – Simone Jan 02 '17 at 22:35
  • I don't want to start another question for such a little problem so I'll try asking here, using fgets combined with strcspn I was able to make the acquisition of the name working in a more secure way. I tried getting the char with an fgets(&c,sizeof c,stdin) but it would just skip it and stop the loop, how would you go about it? – Simone Jan 03 '17 at 10:55
  • [Why is the gets function so dangerous that it should not be used?](http://stackoverflow.com/q/1694036/995714) – phuclv May 04 '17 at 10:30

2 Answers2

-3

This becomes easier, when turning it around: instead of asking for more, wait for empty input

#include <stdio.h>
#include <string.h>
void main(){
        char c, str[5][20];
        int i=0;
        do {
            printf("What's your name?  - (end list with empty string)\n");
            gets(str[i]);
            i++;
        } while (len(str[i-1] > 0) && (i < 5));
    }
-3

You could do it this way.

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

int main() {
    char c[3], str[5][20];
    int i = 0;
    do {
        printf("What's your name?\n");
        if (fgets(str[i], sizeof str[i], stdin)) {
            // input has worked, do something with data
            i++;
        }
        printf("Do you want to insert more?\n");
        if (fgets(c, 3, stdin)) {
            // input has worked, do something with data
        }
    } while (c[0] == 'y');
}

Test

What's your name?
Mallory
Do you want to insert more?
y
What's your name?
Carol
Do you want to insert more?
no

Process finished with exit code 0
Niklas Rosencrantz
  • 25,640
  • 75
  • 229
  • 424