简体   繁体   中英

C linked list problems

I really need your help with my program. I'm a newbie in C and need to create a linked list in my project.

I use xcode on macOS. My code is here:

typedef struct person
{
    char name[500];
    char telnum[16];
    char wohnort[500];
    struct person *next;

}person;

person *head=NULL;
void einlesen()
{
    person *p;
    char name[30];
    char telnum[16];
    char wohnort[30];
    //char buff1[15], buff2[15];
    int cnt=0;

    FILE *fp=fopen("Data2.txt", "r");
    if(fp==NULL)
    {
        printf("File konnte nicht geoeffnet werden!\n");
        exit(1);
    }
    while(fscanf(fp," %29[A-z ]\t%s\t%s", &name, &telnum, &wohnort)!=EOF)
    {

        cnt++;


        printf("Datei gefunden!\nDaten:%s, %s, %s\n", name, telnum, wohnort);


        if(head == NULL){
            head = (person*)malloc(sizeof(person));
            strcpy(head->name, name);
            strcpy(head->telnum, telnum);
            strcpy(head->wohnort, wohnort);
            head->next = NULL;
        }
        else{
            p = head;
            while(p->next != NULL)
            {
                p = p->next;
            }

            p->next = (person*)malloc(sizeof(person));
            strcpy(p->next->name,name);
            strcpy(p->next->telnum,telnum);
            strcpy(p->next->wohnort,wohnort);
            p->next->next = NULL;
        }

    }
    printf("Die Daten von %d Personen wurden eingelesen!\n\n", cnt);
    fclose(fp);
}

void addieren()
{   char name[30];
    char telnum[16];
    char wohnort[30];
    person *p = head;

    printf("Bitte den Namen der hinzufuegenden Person eingeben:\n");
    scanf(" %29s", name);
    while(getchar() != '\n');
    printf("\nBitte die Telefunnumer der hinzufuegenden Person eingeben:\n");
    scanf(" %15s", telnum);
    while(getchar() != '\n');
    printf("\nBitte den Wohnort der hinzufuegenden Person eingeben:\n");
    scanf(" %29s", wohnort);
    while(getchar() != '\n');

    if(p==NULL) return;
    while(p->next)
    {
        p=p->next;
    }
    p->next = (person*)malloc(sizeof(person));
    strcpy(p->next->name, name);
    strcpy(p->next->telnum, telnum);
    strcpy(p->next->wohnort, wohnort);
    p->next->next=NULL;
}

and i have this in my main function:

int main()
{   
    person *p1=head;


    einlesen();
    addieren();
    while(p1 !=NULL)
    {
        printf("Namen: %s\n", p1->name);
        p1=p1->next;
    }

    return 0;

}

It's already read the data from the file and I wanted to add some new records to it and the print to the screen. This returns 0 and doesn't really print the list on the screen.

Later I need to add more functions to my program, like: -deletefromlist -modify element -search in the linked list -save to file -and a menue

You are creating a new person inside the function addieren instead of receiving the one you created on the main function. You need to receive it as an argument, something like that

int addieren(person **head) { ... }

And on the main you should make

addieren(&p1);

Notice the double pointer so you can pass the pointer and modify it inside of the function. Also you probably should return an int to confirm either the operation was succesfull or not

I see no particular question, so I'll start by pointing out some errors, and perhaps when you've added a question (which ends in a question mark) you can ping me for an update.

while(fscanf(fp," %29[A-z ]\t%s\t%s", &name, &telnum, &wohnort)!=EOF)

Let me just start off by saying I'm a huge advocate of reading the manual before using a function for the first time. In fact, I'm pretty sure it's expected of us, as programmers. Granted, we must learn which manuals to seek, because the internet is a dangerous place and people do occasionally lie. The OpenGroup manuals are good. For example, if you type into Google "Opengroup fscanf", you'll find the manual for fscanf , which will answer many questions I', sure...

The manual states that all whitespace is treated the same, as a directive which attempts to read and discard as much whitespace as possible. Hence, a plain space has the same meaning to \\t in a format specifier (at least, in your context)... so if your question is something along the lines of "Why are all whitespaces treated the same?" then the answer is "because that's what the manual says it should do."

The fixed width field you're reading into can fail to translate, in a scenario the manual also describes where-by the first character tested failed to match the criteria ( [Az ] , which looks highly suspect, and you'll probably realise by reading the manual that this isn't what you want). That would result in a return value (from scanf ) of 0 , which, to your code, looks like a successful read.

Here's an idiomatic guideline: Let's first count the number of objects that you want to read into... Here they are, copied verbatim from your code: &name, &telnum, &wohnort ... There are three of them.

Now, take that number, three, and compare it to what fscanf returns... If these two numbers match, then you can use all three arguments safely (though as I note below, they may not necessarily contain the values that you expect them to contain).

You also shouldn't use the & (address-of) operator here for name , telnum or wohnort . The address-of operator on a char [10] array would result in a char (*)[10] expression, where-as you most certainly want a plain vanilla char * expression. Hence, the correct thing to do is to let Cs implicit "array expression to pointer expression" conversion do that for you.

Below is probably closer to what you want. My advice regarding the [Az ] thing is that you list out each of the characters you want to include in those brackets, or use [^...] if you want to list out each of the characters you want to exclude . To be clear, there are no ranges in C format strings, in case that's what your question was about. eg:

while(fscanf(fp," %29[qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM ] %s %s", name, telnum, wohnort)==3)

Note that it isn't quite there, yet. There's the potential for 29 bytes of a 32 byte input to be read into that fixed width field, leaving three characters on the stream. Perhaps they're not space, in which case your whitespace directive will silently fail, and those remaining three characters will be treated as telnum .

You should try to read just one item per call to scanf , if only until you understand the corresponding manual.


No collection should ever require n calls to malloc to store n objects. If you manage to complete this (no doubt self-assigned) task, I suggest making it your next priority to allocate your list as multiple nodes per call to malloc ... or better yet, the convenience you get not having to free() every string fscanf returns , you could benefit from the same technique; expect caller to allocate the list, passing you all the storage you need, as well as items to add, remove, etc from the list. All the function does is modify the objects passed in.


while(getchar() != '\n');

Above you recognise that EOF can occur... what do you think getchar() will return when that happens? Not '\\n' , that's for sure, and it'll keep returning that (not `'\\n') value indefinitely, hence an infinite loop. Trying to solve this problem complicates the loop a bit; you need storage for the character, eg:

int c;
while ((c = getchar()) != EOF && c != '\n');

The clearer alternative to that is actually to use fread , eg

char c;
while (fread(&c, 1, 1, stdin) && c != '\n');

Nonetheless, better yet, is using fscanf , according to how the manual explains (there are many other useful functionalities for you to read about ASAP). Do you think you can remember these two lines, after typing them ten or fifteen times in a row?

scanf("%*[^\n]");
getchar();

Man... your code should always check malloc return values before they're used. How do we know your malloc calls aren't returning NULL , leading to a question which you haven't asked?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM