0

My code to read a string into a struct isn't working. I've tried fgets, gets and also scanf, and none of them is working, returning random characters when I run the code. Can anyonye please help me? Thanks in advance.

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

struct student
{
    char string[100];
};

struct student get_detail(int n)
{
    struct student wannabe;
    if (n==1)
    {
        printf("String:\n");
        scanf("%s", wannabe.string);
        //fgets(wannabe.string, 100, stdin) didn't work;
        //gets (wannabe.string) also didn't work
        //scanf("%s", wannabe.string) didn't work
        return wannabe;
    }
}
void main()
{
    int x = 1;
    struct student test = get_detail(x);
    printf("\nString:%s", test.string);

}

francescobfc
  • 107
  • 1
  • 11
  • 2
    `get_detail` isn't returning anything, so your function has *undefined behavior* – UnholySheep Nov 02 '19 at 22:43
  • Sorry, when reducing the code to post here I've deleted the return part. I will edit the post. It isn't working it it also. – francescobfc Nov 02 '19 at 22:44
  • 2
    Your function still doesn't `return` anything when `n` is not 1. Though on IDEOne this code still works: https://ideone.com/R7VlHW – UnholySheep Nov 02 '19 at 22:46
  • 1
    Just debugged your code in VS 2017, it works perfect as it is. However, you should think about what to return when `n != 1`, and read some input at the end of your `main` so that it doesn't exit immediately. – Javier Silva Ortíz Nov 02 '19 at 23:08
  • 2
    Change return type of `main` to `int`. Your code works for me as you posted it, after fixing to `int main()` and adding `return wannabe;` before closing `}` inside `get_detail`. – KamilCuk Nov 02 '19 at 23:16
  • the function: `gets()` has been depreciated for years and completely removed in the latest version(s) of C. – user3629249 Nov 03 '19 at 01:04
  • regarding: `scanf("%s", wannabe.string);` 1) always check the returned value (not the parameter value) to assure the operation was successful. In the current statement, any returned value other than 1 indicates an error occurred. 2) when using the input format conversion specifier: `%s` and/or `%[...]` always include a MAX CHARACTERS modifier that is 1 less than the length of the input buffer because those specifiers always append a NUL byte to the input, This also avoids any possibility of a buffer overflow and the resulting undefined behavior (cont) – user3629249 Nov 03 '19 at 01:08
  • (cont) note: `%s` will stops inputting when it encounters any `white space` character. Suggest: `if( scanf("%99s", wannabe.string) != 1 ) { fprintf( stderr, "scanf failed to input string\n" );` You might want to look at: `scanf("%99[^\n]", wannabe.string);` as that will input until a newline is encountered or 99 characters are input, which ever comes first – user3629249 Nov 03 '19 at 01:11
  • `fgets()` leaves a trailing `'\n'` (assuming input from the user is not longer than the buffer). `scanf("%s",...)` does not. – Peter Nov 03 '19 at 01:13
  • `printf("\nString:%s", test.string);` --> `printf("\nString:<%s>\n", test.string);` (Flush the output) – chux - Reinstate Monica Nov 03 '19 at 05:02

1 Answers1

3

The @Kamil Cuk is right: Change return type of main to int. Your code works for me as you posted it, after fixing to int main() and adding return wannabe; before closing } inside get_detail

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

struct student 
{
    char string[100];
};

struct student get_detail(int n)
{
    struct student wannabe;
    char ch;

    if (n == 1)
    {
        printf("String:\n");
        fgets(wannabe.string, 100, stdin);
        strtok(wannabe.string, "\n");
        if (strlen(wannabe.string) == 100 - 1) 
        {
            while ((ch = getchar()) != '\n' && ch != EOF); // getchar() in loop to clean stdin
        }
        wannabe.string[strcspn(wannabe.string, "\n")] = 0; // to remove '\n' if the user does not type anything
    }

    return wannabe;
}

int main()
{
    int x = 1;
    struct student test = get_detail(x);
    printf("\nString: %s\n", test.string);

    return 0;
}
  • I'm sorry. I don't speak english yet and i'm new here –  Nov 03 '19 at 03:57
  • `strtok(wannabe.string, "\n");` fails to remove the `'\n'` when buffer is `"\n"`. It will if other characters read. Not a uniform way of removing `'\n'`. – chux - Reinstate Monica Nov 03 '19 at 05:00
  • strtok removes '\n' from string and not from buffer. The '\n' is removed from the buffer with the getchar command. I recommend debugging the code or entering the scanf ("%*c") command before wannabe is returned –  Nov 03 '19 at 11:20
  • Limit string length to 6 and type "hello baby" leaving scanf as I said. Result: "hello\0" –  Nov 03 '19 at 11:33
  • 1
    "strtok removes '\n' from string" --> it does not when `'\n'` is first. Try `char s[] = "\n"; strtok(s, "\n"); printf("<%s>\n", s);` to see that. – chux - Reinstate Monica Nov 04 '19 at 04:08
  • Let's look at the return of the strtok function: `char s[] = "\n";` `char *token;` `token = strtok(s, "\n");` `printf("<%s>", token);` –  Nov 04 '19 at 10:45
  • Now `'\n'` not being the first: `char s[] = "abc\n";` `char *token = NULL;` `token = strtok(s, "\n");` `printf("<%s>", token);` –  Nov 04 '19 at 11:00
  • Posted code does not use the return value of `strtok()`, so the 2 examples do not directly apply. Code uses `strtok(wannabe.string, "\n");` and later `return wannabe;`. Thus the calling code can print `"\nString: \n\n"`. Certainly an unexpected output. Good alternative: [Removing trailing newline character from fgets() input](https://stackoverflow.com/a/28462221/2410359) – chux - Reinstate Monica Nov 04 '19 at 14:37
  • Now it's clear that the issue is that you didn't like my code. Nothing against. I see it as something personal –  Nov 04 '19 at 20:37
  • 1
    Nothing personal. It is simple that the code removes the `'\n'` in many cases, yet not in the case of user input beginning with `'\n'`. – chux - Reinstate Monica Nov 04 '19 at 20:57
  • I followed your recommendation: I edited the code. Thanks! –  Nov 05 '19 at 00:58