1

I'm newbie here and there is some question that I want have some lesson from you guys. For example:

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

void main()
{
    char name[51],selection;

    do
    {

    printf("Enter name: ");
    fflush(stdin);
    fgets(name,51,stdin);
    printf("Enter another name?(Y/N)");
    scanf("%c",&selection);
    selection=toupper(selection);
    }while (selection=='Y');
                     //I want to printout the entered name here but dunno the coding
printf("END\n");
system("pause");
}

As I know when the loops perform will overwrite the variable then how I perform a coding that will printout all the name user entered? I have already ask my tutor and he is ask me to use pointer, can anyone guide me in this case?

Wilson
  • 29
  • 6
  • As you got answer, you need container. Also, in Unix world, EOF is usually used as end of input, not interactive questions. – KAction Jul 07 '12 at 03:15
  • if you're just printing the names, you could have a single array containing all the names, separated by a sentinel, 'n', 'a', 'm', 'e', '1', 's', 'e', 'n', 't', 'i', 'n', 'e', 'l', 'n', 'a', 'm', 'e', '2',..., just trowing an idea... –  Jul 07 '12 at 03:43
  • 2
    `gets(name);` Never ever ever ever use that. `gets()` is a function which is impossible to use correctly. It is removed from C11 and deprecated in C99. Every single usage of this function is a gaping security hole, and an entry point for bugs. – Dave Jul 07 '12 at 04:46
  • thanks for you guys valuable comment, i have edit my gets(name) to use with scanf("%[^\n]",name). can anyone show some example which can store string in a loop and print it out all the string stored? – Wilson Jul 07 '12 at 05:09
  • 1
    @user1508163, an unconstrained `scanf` is no different. `fgets(name, sizeof name, stdin);` Is the right way to get a line in C. It does leave the newline character at the end, though. – Dave Jul 07 '12 at 05:11
  • Dave, thanks so much for your advice, already edited my post. Really appreciate it. – Wilson Jul 07 '12 at 05:21
  • Dave, can giving me some example for collect all the string that entered? Trust for your expert skill. Thank you so much. – Wilson Jul 07 '12 at 05:28

3 Answers3

1

You've basically got two options, create a list of all the names, looping through each of them at the end, or concatenate all the names into a string as you read them, and print that whole buffer at the end. The first goes roughly like this:

 char ch[2]="Y", names[100][52]; //store up to 100 50-char names (leaving space for \n and \0)
 int x, nnames=0;
 while(nnames<100 && *ch=='Y'){
     fgets(names[nnames++], sizeof names[0], stdin); //since names is a 2d array, look
     //only at the length of a row, (in this case, names[0])
     fgets(ch, 2, stdin);
     *ch = toupper(*ch);
 }
 for(x=0; x<nnames; x++)
     //print names[x].

And the second goes roughly like this:

 char names[100*52], *np=names, *ep=names+sizeof names; //an array, the position, and the end
 char ch[2]="Y";
 while(np<ep && *ch=='Y'){
      fgets(np, ep-np, stdin); //read a name, and a newline into the buffer
      //note how I use the difference between the end and the position to tell
      //fgets the most it can possibly read
      np+=strlen(np); //advance the position to the end of what we read.
      //same deal with the y/n stuff...
 }
 printf("%s", names);

Notice the lack of loop at the end, because the whole string is stored in names.

Dave
  • 10,964
  • 3
  • 32
  • 54
  • Ops,`shift+7`==>`&` I mistyped – Dave Jul 07 '12 at 05:48
  • Ha! Thanks mate!! Really appreciate it!! By the way in the first coding why have to put asterisk before ch? means '*ch=="Y"' and '*ch = toupper(*ch)' sorry for newbie question... – Wilson Jul 07 '12 at 06:20
  • No need to apologize for reasonable questions. You'll notice I declare `char ch[2]` (a 2-element array). `*ch` is shorthand for `ch[0]`. I make `ch` an array, because I am using `fgets` for input, and it needs room both for the `y/n` and a newline. – Dave Jul 07 '12 at 06:33
  • Thanks for your nice explanation and your help, thank you so much. hopes to seek for your help again in future. – Wilson Jul 07 '12 at 06:40
  • By the way is there any safe coding to get value of double,float and integer? As I know fgets() is only for string and character. – Wilson Jul 07 '12 at 06:44
  • Using `scanf` works, because the length of a float or double is known in advance; the length of a string can't be known unless specified. Nevertheless, `scanf` alone usually introduces subtle bugs, because of the way it interacts with the `stdin` buffer, and newlines. Use `fgets` to read the whole line into a buffer, then `sscanf`, `atoi`, `strtod`, etc... to parse the line. – Dave Jul 07 '12 at 10:03
  • @Dave Thanks for your fast reply. By the way if using fgets(), it will automatic enter a new line in the result. If I don't want the new line, what should change in this function? – Wilson Jul 07 '12 at 11:11
  • Write a wrapper for it, which calls fgets, then strips the newline out with something like `str[strlen(str)-1]='\0'` – Dave Jul 07 '12 at 11:18
  • @Dave for example fgets(name[countname],51,stdin); name[strlen(name)-1]='\0'; it shows name is imcompatible with const char. – Wilson Jul 07 '12 at 11:30
  • Essentially; but you can put the `fgets` and the newline stripping in a single function. This discussion has gotten rather off-topic; though. If you need further guidance, try to research some, and if you reach a specific problem, ask another SO question. – Dave Jul 07 '12 at 11:37
  • Thanks for helping alot. I will try to do some research first. Sorry for troublesome. – Wilson Jul 07 '12 at 11:39
0

You can use a linked list to store all the entered names. All data structure books talk about linked list a lot.

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

struct name_node
{
    char name[100];
    struct name_node *next;
};

struct name_node* add_name(struct name_node *first, const char *name)
{
    struct name_node *p;

    /* create our node */
    p = (struct name_node*)malloc(sizeof(struct name_node));
    strcpy(p->name, name);
    p->next = NULL;

    /* link our node to the tail */
    if (first) {
        for (; first->next; first = first->next);
        first->next = p;
    }

    return p;
}

void print_names(struct name_node *first)
{
    /* print names stored in the list */
    for (; first; first = first->next) {
        printf("%s\n", first->name);
    }
}

/* free the memory we used */
void destroy_list(struct name_node *first)
{
    if (first) {
        if (first->next)
            destroy_list(first->next);

        free(first);
    }
}

int main(void)
{
    struct name_node *head = NULL;
    struct name_node *node;
    char name[100];
    char selection;

    do {
        printf("Enter name: ");
        fflush(stdin);
        fgets(name, 51, stdin);

        /* save the user input to a linked list */
        /* save head if we don't have head */
        node = add_name(head, name);
        if (!head)
            head = node;

        printf("Enter another name?(Y/N)");
        scanf("%c", &selection);
        selection = toupper(selection);
    }
    while (selection == 'Y');

    /* print the list if we have any data */
    if (head)
        print_names(head);

    /* free the memory we used */
    destroy_list(head);

    printf("END\n");
    system("pause");

    return 0;
}
Rango
  • 1,087
  • 7
  • 5
0

Use a single string to get all names:

char allnames[1000] = "";

do {
    //get name in fgets
    selection = toupper(selection);
    strcat(allnames, selection);

    //Check for repetion

} while (/*there is repetion*/);

printf("%s", allnames);

You've to select the size of allnames suitably to store all names.

mohit
  • 5,696
  • 3
  • 24
  • 37
  • 1
    -1 This doesn't discourage `gets`, still overwrites the last entered name each time, and mistakes `toupper` for something that works on a whole string. – Dave Jul 07 '12 at 04:51
  • It doesn't. Now it invokes undefined behavior "The behavior of this function is undefined if copying takes place between objects that overlap—for example, if s is also given as an argument to be printed under control of the ‘%s’ conversion." See [this so question](http://stackoverflow.com/questions/1283354/is-sprintfbuffer-s-buffer-safe) for more. – Dave Jul 07 '12 at 05:03
  • thx for your valuable reply, but it print nothing like skipping the sprint step. – Wilson Jul 07 '12 at 05:05
  • I've removed my downvote, because you have addressed most of my complaints. I will note; however, that you still misuse `toupper`, and that `strcat` introduces a hidden `O(n)`, because it can't hold onto the end of the string. – Dave Jul 07 '12 at 06:06
  • thanks, next time i answer i will take some time to do some research. – mohit Jul 07 '12 at 06:10