簡體   English   中英

printf 不會為 int 正確打印 %d 的輸出

[英]printf will not print output of %d correctly for an int

無法弄清楚為什么我的 printf 輸出無法正確打印 int data.age 或 addr.zip。 它們被定義為 int,所以 %d 應該可以工作......但它沒有。 我得到了輸出的亂碼。 所有其他領域都完美地工作。

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

typedef struct BillingAddress {
    char *street[50];
    char *city[25];
    char *state[3];
    int *zip[6];

}address;

address addr;

typedef struct ContactInfo {
    char *name[30];
    int *age[3];
    char *phone[15];
    struct BillingAddress PersonalData;
}personaldata;

personaldata data;

int main()
{
    printf("Enter your full name: ");
    scanf(" %49[^\n]", &data.name);
    printf("Enter your age: ");
    scanf("%d", &data.age);
    printf("Enter your Phone Number (xxx) xxx-xxxx: ");
    scanf(" %14[^\n]", &data.phone);
    printf("Enter your street address: ");
    scanf(" %49[^\n]", &addr.street);
    printf("Enter your city: ");
    scanf(" %24[^\n]", &addr.city);
    printf("Enter your state abbreviation: ");
    scanf("%s", &addr.state);
    printf("Enter your zip code: ");
    scanf("%d", &addr.zip);

    printf("Personal Data: \n %s\n %d\n %s\n %s\n %s\n %s\n %d\n", data.name, data.age, data.phone, addr.street, addr.city, addr.state, addr.zip);
}

讓我們一步一步來。 BillingAddress結構定義中,您打算存儲街道、城市和州。 您可以將所有這些參數表示為字符串(在 C 中是字符數組),這似乎是合乎邏輯的。 我相信這就是你試圖做的,但聲明:

char *street[50];

代表給你一個 50 個char * (即char指針)的數組,而不是 50 個chars ,這是你真正想要的。 因此,結構定義應該是:

typedef struct BillingAddress {
    char street[50];
    char city[25];
    char state[3];
    int zip;
} address;

您還打算存儲 zip。 請注意我如何將zip的類型更改為int數組而不是int數組。 你可以做一個int數組,但你必須做更多的工作才能正確接受用戶的輸入(簡單地使用scan("%d", &addr.zip)行不通的)。

現在,讓我們看一下定義ContactInfo結構體的另一種方式:

typedef struct ContactInfo {
    char name[30];
    int age;
    char phone[15];
    address addr;
} personaldata;

您可以看到我刪除了*並將age更改為單個int ,原因與我上面提到的類似。 我還用更簡單的address替換了struct BillingAddress 為什么? 因為您創建了一個typedef將關鍵字address鏈接到struct BillingAddress 因此,通過單獨使用address ,代碼看起來更簡潔一些,並且您可以很好地使用該typedef :D (請注意,使用struct BillingAddress並沒有什么不正確,我只是認為使用typedef看起來更干凈)。

此外,您會看到我將address類型的變量(即struct BillingAddress類型——記住typedef意味着這兩個是相同的)重命名為addr 這比將其命名為PersonalData更有意義,因為它是一個地址,而不是任意的個人數據。

現在轉到您的main()方法。 您應該了解使用scanf()的一些陷阱。 由於它從默認輸入流stdin (即很可能是您的終端)讀取,因此任何未被scanf()吞入的字符都將留在輸入流中。 因此,對scanf()任何后續調用也將讀取那些不需要的字符。 有關更多信息,請參閱此帖子 如果您提供的字符數少於所需字符的最大數量,您可能不會遇到這種情況,但處理此錯誤情況很重要。 因此,在每次scanf() ,您應該清除輸入流,這可以使用以下方法完成:

void clear_input_stream()
{
    int c;
    while ((c = fgetc(stdin)) != '\n' && c != EOF);
}

您可以在每次scanf()調用后調用此方法。

您想確保如果您正在寫入char數組,則不應在要寫入的變量前添加& - 檢查此答案以獲取解釋(您的編譯器應該警告您)。

我要提到的最后一件事是,您還可以向%d說明符添加長度以限制讀取特定長度的整數。 您的main()可能如下所示:

int main()
{
    printf("Enter your full name: ");
    scanf(" %49[^\n]", data.name); 
    clear_input_stream();
    printf("Enter your age: ");
    scanf(" %3d", &data.age); 
    clear_input_stream();
    printf("Enter your Phone Number (xxx) xxx-xxxx: ");
    scanf(" %14[^\n]", data.phone); 
    clear_input_stream();
    printf("Enter your street address: ");
    scanf(" %49[^\n]", addr.street); 
    clear_input_stream();
    printf("Enter your city: ");
    scanf(" %24[^\n]", addr.city); 
    clear_input_stream();
    printf("Enter your state abbreviation: ");
    scanf(" %2[^\n]", addr.state); 
    clear_input_stream();
    printf("Enter your zip code: ");
    scanf(" %5d", &addr.zip); 
    clear_input_stream();

    printf("Personal Data: \n %s\n %d\n %s\n %s\n %s\n %s\n %d\n", data.name, data.age, data.phone, addr.street, addr.city, addr.state, addr.zip);

    return 0;
}

暫無
暫無

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

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