繁体   English   中英

C 读取字符串字符时出错。 尝试从字符串打印但没有成功

[英]C error reading characters of string. tring to print from string without success

我正在编写一个代码,我需要从“addReasons”function 中获取字符串并打印我在其他 function 中得到的所有字符串,如果有人能告诉我如何修复它,我会收到运行时错误,上面写着“读取字符串的字符时出错”会很有帮助。 谢谢你。

像这样调用 function :

addReasons(&proList);
addReasons(&conList);
printList(proList);
printList(conList);

编码:

typedef struct reasonList
{
    char* listName;
    char* reasons[MAX_LIST_LENGTH];
    int numReasons;
} reasonList;

/*
Function will add a reason to the list
input: the list to add to and its name
output: none
*/
void addReason(reasonList* list)
{
    int index = 0;
    index = list->numReasons;
    if (index < MAX_LIST_LENGTH)
    {
        printf("Enter a reason to add to list %s: ", list->listName);
        fgets(&list->reasons[index], STR_LEN, stdin);
        list->numReasons++;
    }
}
/*
Function will print a list of reasons
input: the list
output: none
*/
void printList(reasonList list)
{
    int i = 0;
    printf("List %s\n", list.listName);
    printf("---------\n");
    for (i = 0; i < list.numReasons; i++)
    {
        printf("%s\n", list.reasons[i]);
    }
}

fgets需要一个char*参数,但您传递了一个char**参数。 编译器对此发出警告:

warning: incompatible pointer types passing 'char **' to parameter of type 'char *';
remove & [-Wincompatible-pointer-types]
   fgets(&list->reasons[index], STR_LEN, stdin);
         ^~~~~~~~~~~~~~~~~~~~~

正确的方法是:

    fgets(list->reasons[index], STR_LEN, stdin);

但是,现在这将使用未初始化的指针。 因此,您需要首先为该字符串分配 memory 并使用该地址初始化指针:

    list->reasons[index] = malloc(STR_LEN);
    fgets(list->reasons[index], STR_LEN, stdin);

您还需要在完成后free() memory,否则如果您的程序长时间运行,您将泄漏 memory。

结构体reasonList的数据成员reasons是一个char *类型的指针数组。

char* reasons[MAX_LIST_LENGTH];

所以这个fgets调用的第一个参数

fgets(&list->reasons[index], STR_LEN, stdin);

具有char **类型,而 function 需要char *类型的参数。 所以这个调用会调用未定义的行为。

同样从提供的代码中,还不清楚这些指针(数组的元素)是否指向字符 arrays。 如果您没有动态分配指针将指向的字符 arrays 那么如果您甚至可以正确写入

fgets( list->reasons[index], STR_LEN, stdin); 

然而,再次这样的调用将调用未定义的行为。

考虑到错误消息,您似乎确实忘记分配将由数组的元素(指针)指向的字符 arrays。

考虑到 function fgets可以 append 换行符'\n'到您应该删除的输入字符串。

例如,function 可以通过以下方式查看

int addReason( reasonList *list )
{
    int success = list->numReasons < MAX_LIST_LENGTH;
 
    if ( success )
    {
        list->reasons[list->numReasons] = malloc( STR_LEN );
        success = list->reasons[list->numReasons] != NULL;

        if ( success )
        {
            list->reasons[list->numReasons][0] = '\0';

            printf( "Enter a reason to add to list %s: ", list->listName );
            if ( fgets( list->reasons[list->numReasons], STR_LEN, stdin ) != NULL )
            {
                list->reasons[list->numReasons][ strcspn( list->reasons[list->numReasons], "\n" ) ] = '\0';
            }
            
            ++list->numReasons;
        }
    }

    return success;
}

问题的另一个原因可能与您应该使用字符串文字分配的数据成员listName相关,或者您需要再次动态分配将由数据成员指向的字符数组。

顺便说一句,function printList应该声明为

void printList( const reasonList *list );

代替

void printList( const reasonList *list );

因为创建一个 struct reasonList类型的 object 的副本而不是传递一个指向它的指针是低效的。

这是一个演示程序。

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

#define MAX_LIST_LENGTH 10
#define STR_LEN 50

typedef struct reasonList
{
    char* listName;
    char* reasons[MAX_LIST_LENGTH];
    int numReasons;
} reasonList;

int addReason( reasonList *list )
{
    int success = list->numReasons < MAX_LIST_LENGTH;
 
    if ( success )
    {
        list->reasons[list->numReasons] = malloc( STR_LEN );
        success = list->reasons[list->numReasons] != NULL;

        if ( success )
        {
            list->reasons[list->numReasons][0] = '\0';

            printf( "Enter a reason to add to list %s: ", list->listName );
            if ( fgets( list->reasons[list->numReasons], STR_LEN, stdin ) != NULL )
            {
                list->reasons[list->numReasons][ strcspn( list->reasons[list->numReasons], "\n" ) ] = '\0';
            }
            
            ++list->numReasons;
        }
    }

    return success;
}

void printList( const reasonList *list )
{
    printf( "List %s\n", list->listName);
    printf("---------\n");
    for ( int i = 0; i < list->numReasons; i++ )
    {
        printf( "%s\n", list->reasons[i] );
    }
}

int main(void) 
{
    reasonList list = { .listName = "List of reasons", .numReasons = 0 };
    
    addReason( &list );
    
    printList( &list );
    
    return 0;
}

程序 output 可能看起来像

Enter a reason to add to list List of reasons: Unallocated memory
List List of reasons
---------
Unallocated memory

如果您出于动态原因分配 memory,那么您应该在退出程序之前释放所有已分配的 memory。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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