【问题标题】:how to fill an array of pointers in c如何在c中填充指针数组
【发布时间】:2020-11-23 08:33:05
【问题描述】:

我想按以下格式填充一个 char 指针数组:

[姓名、电子邮件地址数量、所有电子邮件地址]*人数。每个人的邮件地址数量一开始是未知的。

  • 我必须使用 char *contacts[N]
  • 打印数组时只打印联系人[0],所以我猜我扫描输入的方式是错误的

这是我目前为止的主要内容:

int main()
{
    char *contacts[N];
    int nextAvailable = 0;
    int * const nextAvailableP = &nextAvailable;
    add(contacts, nextAvailableP);
    //Printing this way will only print contacts[0]
    int i;
    for (i = 0; i < nextAvailable; i++) {
        printf("%s", contacts[i]);
    }
}

这是添加函数:

int add(char *contacts[], int *nextAvailableP) {
    if (*nextAvailableP > 97) {
        printf("Not enough memory\n");
        return FALSE;
    }

    char tempName[50];
    char tempMail[50];
    int numberOfMails = 1;

    printf("Enter your name\n");
    fgets(tempName, 50, stdin);
    if ((strlen(tempName) > 0) && (tempName[strlen(tempName) - 1] == '\n'))
        tempName[strlen(tempName) - 1] = '\0';

    contacts[*nextAvailableP] = (char *)malloc((strlen(tempName) + 1));

    if (contacts[*nextAvailableP] == NULL) {
        printf("Not enough memory\n");
        return FALSE;
    } else {
        strcpy(contacts[*nextAvailableP], tempName);
    }

    (*nextAvailableP)++;
    int numberOfMailsIndex = *nextAvailableP;
    itoa(numberOfMails, contacts[numberOfMailsIndex], 10);
    (*nextAvailableP)++;
    

    printf("Enter your mail/s, use enter to enter a mail and '-1' to signal you finished\n");
    fgets(tempMail, 50, stdin);

    while (strcmp(tempMail, "-1") != 0) {
        if ((strlen(tempMail) > 0) && (tempMail[strlen(tempMail) - 1] == '\n')) {
            tempMail[strlen(tempMail) - 1] = '\0';
        }

        contacts[*nextAvailableP] = (char *)malloc((strlen(tempMail) + 1));
        
        if (contacts[*nextAvailableP] == NULL) {
            printf("Not enough memory");
            return FALSE;
        } else {
            strcpy(contacts[*nextAvailableP], tempMail);
        }
        (*nextAvailableP)++;
        numberOfMails++;
        itoa(numberOfMails, contacts[numberOfMailsIndex], 10);
        fgets(tempMail, 50, stdin);
    }
}

我以为我正在将联系人中的每个单元格初始化为请求的大小,然后将我从用户那里扫描的单词复制到其中 - 但显然我不是。我应该逐个字符地遍历我分配的每个内存吗?

顺便说一句,我知道不需要强制转换为 *char

【问题讨论】:

  • 永远不要使用gets()。这是一个危险的功能,已从语言中删除。请改用fgets()
  • 这是什么:contacts[*nextAvailableP] = numberOfMails;contacts 是一个字符串数组,你不能把numberOfMails 放在那里。
  • 您应该使用结构数组。每个结构都可以包含名称、电子邮件数量和指向电子邮件数组的指针。
  • @Barmar 我必须使用 char *contacts[N] 作为问题的一部分。对于contacts[*nextAvailableP] = numberOfMails,我会投,谢谢
  • @RedYoel 你实际上并没有提到你到底得到了什么错误。它没有得到输入吗?是输出格式错误,还是什么都没有发生?

标签: c pointers malloc


【解决方案1】:

所以这将是您更正的代码

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

#define MAX_ENTRIES 50

int add(char *contacts[], int *nextAvailable);

int main(void){
    int i;
    char *contacts[MAX_ENTRIES];
    int nextAvailable = 0;
    add(contacts, &nextAvailable);
    add(contacts, &nextAvailable);

    for(i=0; i < nextAvailable ; i++){
        printf("%s\n", contacts[i]);
    }
}

char* intToString(int val, int base){
    //source: www.strudel.org.uk/itoa/
    static char buf[32] = {0};

    int i = 30;

    for(; val && i ; --i, val /= base)

        buf[i] = "0123456789abcdef"[val % base];

    return &buf[i+1];

}

int add(char *contacts[], int *nextAvailableP) {
    if (*nextAvailableP > 97) {
        printf("Not enough memory\n");
        return 0;
    }

    char tempName[50];
    char tempMail[50];
    int numberOfMails = 1;

    printf("Enter your name\n");
    fgets(tempName, 50, stdin);
    if ((strlen(tempName) > 0) && (tempName[strlen(tempName) - 1] == '\n'))
        tempName[strlen(tempName) - 1] = '\0';

    contacts[*nextAvailableP] = (char *)malloc((strlen(tempName) + 1));

    if (contacts[*nextAvailableP] == NULL) {
        printf("Not enough memory\n");
        return 0;
    } else {
        strcpy(contacts[*nextAvailableP], tempName);
    }

    (*nextAvailableP)++;
    int numberOfMailsIndex = (*nextAvailableP);
    contacts[numberOfMailsIndex] = malloc(5);
    (*nextAvailableP)++;

    printf("Enter your mail/s, use enter to enter a mail and '-1' to signal you finished\n");
    fgets(tempMail, 50, stdin);

    while (strcmp(tempMail, "-1\n") != 0) {
        if ((strlen(tempMail) > 0) && (tempMail[strlen(tempMail) - 1] == '\n')) {
            tempMail[strlen(tempMail) - 1] = '\0';
        }

        contacts[*nextAvailableP] = (char *)malloc((strlen(tempMail) + 1));

        if (contacts[*nextAvailableP] == NULL) {
            printf("Not enough memory");
            return 0;
        } else {
            strcpy(contacts[*nextAvailableP], tempMail);
        }
        (*nextAvailableP)++;
        numberOfMails++;
        fgets(tempMail, 50, stdin);
    }
    strcpy(contacts[numberOfMailsIndex], intToString(numberOfMails - 1,10));

}

【讨论】:

  • contacts[numberOfMailsIndex] = malloc(5); 是我错过的那一行,谢谢!我给它分配了 1 个字节,也可以吗?
  • 一个字节是不够的。提醒一下,一个字符是一个字节。如果您有 10 个电子邮件地址,则您有 '1' '0' '\0'。所以 3 个字节。
  • @RedYoel 如果你直接写一个8位整数,你只需要1个字节来存储最多255个。但是如果你将它转换成ASCII,你不能在1个字节中存储任何东西。跨度>
【解决方案2】:

您的函数 add 可以在从用户那里获取字符串的子函数中剪切。该字符串将存储在分配的内存空间中,其大小为字符串。

请记住:在一个数组(姓名和电子邮件)中混合不同性质的数据并不是一个好习惯。使用结构会更好(正如@Barmar 所说)。

我会执行以下步骤:

  • 从用户处获取名称(字符 *)
  • 分配内存并将名称复制到其中。
  • 将指向此分配内存的指针插入到您的数组(联系人)中
  • 获取电子邮件地址并将其放入动态分配的内存空间中
  • 将其指针添加到您的数组(联系人
  • 增加电子邮件计数器
  • 重复
  • 检测到-1
  • 将您的电子邮件计数器转换为字符串并将指针转换为您的数组

无论如何,这里有一个代码,你可以开始玩:

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

#define MAX_ENTRIES 50
#define BUFFERSIZE 50

int add(char *contacts[], int *nextAvailable);
char *getString(char *queryText);
char* intToString(int val, int base);

int main(void){
    int i;
    char *contacts[MAX_ENTRIES];
    int nextAvailable = 0;
    add(contacts, &nextAvailable);
    add(contacts, &nextAvailable);

    for(i=0; i < nextAvailable ; i++){
        printf("%s", contacts[i]);
    }
}

int add(char *contacts[], int *nextAvailable){
    if(*nextAvailable > MAX_ENTRIES - 1){
        printf("Not enough memory\n");
        return 1;
    }

    contacts[*nextAvailable] = getString("Enter your name\n");
    if(contacts[*nextAvailable] == NULL){
        printf("Malloc Error\n");
        return 1;
    }
    ++(*nextAvailable);
    int counterfield = *nextAvailable;
    ++(*nextAvailable);
    int emailCounter = 0;
    while(1){

        if(*nextAvailable > MAX_ENTRIES - 1){
            printf("Not enough memory\n");
            return 1;
        }
        char *email = getString("Enter email\n");
        if(strcmp(email, "-1\n") == 0){

            contacts[counterfield] = malloc(5);
            contacts[counterfield] = intToString(emailCounter,  10);

            return 0;
        }
        emailCounter++;
        contacts[*nextAvailable] = email;
        ++(*nextAvailable);

    }


}


char *getString(char *queryText){
    char buffer[BUFFERSIZE];
    char *ret;
    printf("%s", queryText);

    fgets(buffer, BUFFERSIZE, stdin);
    ret = malloc(strlen(buffer));

    strcpy(ret, buffer);
    return ret;
}

char* intToString(int val, int base){
    //source: www.strudel.org.uk/itoa/
    static char buf[32] = {0};

    int i = 30;

    for(; val && i ; --i, val /= base)

        buf[i] = "0123456789abcdef"[val % base];

    return &buf[i+1];

}

【讨论】:

  • 谢谢,我会考虑的,但我想知道我的代码有什么问题。我尝试使用 ITOA,没有任何改变
  • 联系人[numberOfMailsIndex] = (numberOfMails + '0');那是错的。联系人是一个指针数组。所以 (numberOfMails + '0') 将是一个指针。所以如果 numberOfMails 是 5 那么你有一个指向 0x5+0x30 (0x35) 的指针。那不是指向字符串的有效地址。你需要做一个 malloc 并做一个 int 到字符串
  • 另一个错误是您将输入与“-1”进行比较。但 fget 也得到了 \n 。所以试着和“-1\n”比较,比如while (strcmp(tempMail, "-1\n") != 0) {
  • 我实际上是在“清理”'\0'。当输入“-1”时,while 停止。如前所述,ITOA 没有区别。我试过itoa(numberOfMails, &amp;contacts[*nextAvailableP], 10)
  • 您在“清洁”之前比较“-1”。我不明白你如何能够退出你的循环。您是否分配了传递给 itoa 的字符串?第二个参数必须是指向已分配内存空间的指针。查看我使用您更正的代码发布的其他回复
猜你喜欢
  • 1970-01-01
  • 2016-08-06
  • 1970-01-01
  • 1970-01-01
  • 2017-11-07
  • 1970-01-01
  • 2017-10-23
  • 1970-01-01
  • 2018-11-03
相关资源
最近更新 更多