簡體   English   中英

輸入字符串到結構數組的char指針成員

[英]Input string to a char pointer member of an array of structure

我正在嘗試將字符串輸入到結構數組的char類型的指針成員。 程序在收到成員名稱emp [0]的字符串后終止。 我的代碼:

#include<stdio.h>
struct Employee
{
    char *name;
    int salary;
};

int main()
{
    struct Employee emp[3];

    int i;
    for(i=0;i<3;i++)
    {
        scanf("%s%d",emp[i].name,&emp[i].salary);
    }
    printf("\nOutput:");
    for(i=0;i<3;i++)
    {
        printf("\n%s%d",emp[i].name,emp[i].salary);
    }

    return 0;
}

如果不使用數組,則以下用於某些變量emp代碼可以正常工作:

scanf("%s%d",emp.name,&emp.salary);

有什么建議么? 提前致謝。

struct Employeename字段是一個指針。 您永遠不會給該指針一個值,而是將其傳遞給scanf ,然后它嘗試取消引用它。 取消引用未初始化的指針會調用未定義的行為

而不是使用char *作為name ,而是使它成為足以容納您期望的任何值的數組:

struct Employee
{
    char name[50];
    int salary;
};

您需要先初始化char指針name然后才能將其指向用戶輸入的String

#include<stdio.h>
struct Employee
{
    char *name;
    int salary;
};

int main()
{
    struct Employee emp[3];

    int i;
    for(i=0;i<3;i++)
    {
        emp[i].name = (char*)malloc(3);
        scanf("%s%d",emp[i].name,&emp[i].salary);
    }
    printf("\nOutput:");
    for(i=0;i<3;i++)
    {
        printf("\n%s%d",emp[i].name,emp[i].salary);
    }

    return 0;
}

或者,您可以先分配一些name然后再將其傳遞給scanf

emp[i].name = malloc(sizeof*emp[i].name*MAX_LEN);
if( !emp[i].name )
// error in malloc.

您的代碼會怎樣?

scanf嘗試將讀取的字符寫到name包含的地址中。 name包含的地址不確定(某些垃圾值)。 訪問它需要未定義的行為。

如果不使用數組,則以下用於某些變量emp的代碼可以正常工作!

它可以工作,但這是未定義的行為。 下次您運行相同的代碼時,可能會引發錯誤。

ifmalloc之后是什么?

萬一malloc無法提供所請求的內存,它將返回NULL 您正在檢查以確保已分配內存,否則將無法訪問它,因為它會調用未定義的行為。

還有別的事嗎??

是的,除了這一切,還有幾件事

  • 不要轉換malloc的返回類型。 沒必要
  • 使用完動態分配的內存后,請釋放它。 (使用free() )。
  • 檢查scanf返回值,以確保scanf調用是否成功。

回復用戶評論:

如果在struct中有name[4] ,則應編寫scanf("%3s",emp[i].name) 3sscanf讀取的字符限制為3避免緩沖區溢出。 關鍵是,如果您輸入的字符數超過3個,則您只會讀取3個字符,其余字符將出現在輸入流中。

注意:問題以OR開頭,因為另一種方法是dbush回答的問題。 我不想重復。

通過對其他好的答案進行一點改進,我想介紹這個版本。

  1. 我們必須始終檢查malloc()返回,以確保在堆上分配某些所需的內存位置時成功或失敗。 如果失敗,則任何嘗試訪問該未分配內存的操作都會導致未定義行為。
  2. 我們一定不要在C中malloc()返回類型。 為什么不強制轉換malloc()的返回是危險的,請參閱第一個答案。
  3. 使用malloc()時顯式#include <stdlib.h>

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

struct Employee
{
    char *name;
    int salary;
};

int main(){


struct Employee emp[3];

printf("Enter name, salary\n");

int i;
for(i=0;i<3;i++){
    emp[i].name = malloc(40*sizeof(char));

    if (emp[i].name != NULL){
                scanf("%s %d", emp[i].name, &emp[i].salary);
            }else{
                    ///If this accur, try to access inside below for loop is UB
                    printf("Cant allocate Memory for name[%d]\n", i);
            }
}

printf("\nOutput:\n");
for(i=0;i<3;i++)
{
    printf("%s: %d\n", emp[i].name, emp[i].salary);
}

///Free allocated memory 
printf("Free allocated memory\n");
for(i=0;i<3;i++)
{
    free(emp[i].name);
}

return 0;
}

編譯並運行

gcc -Wall so.c -o so && ./so

[暗示]

您必須在姓名和工資整數之間插入一個空格或按Enter鍵。 盡管這可行,但是我建議為每個部分單獨分配scanf()以獲得用戶輸入的姓名,薪金,然后按回車鍵,這是可讀的, 我認為

    scanf("%s", emp[i].name);
    scanf("%d", &emp[i].salary);

[ 注意事項 ]

  1. 嘗試避免使用scanf() 感謝@Jonathan Leffler提供了我其中竊取的鏈接

  2. 我建議看看scanf()將新行char留在緩沖區中 ,當scanf()掃描字符" %c"留一個前導空格

  3. malloc()文檔

[去做]

  1. scanf()行為中的"%c""%d"之間的相似性進行一些研究,刪除緩沖區。
  2. 提供一些解釋,有關堆,堆棧的鏈接。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM