0

因此,我正在尝试编写一个 C 程序,该程序从命令行接收一个字符串,并遍历该字符串并使用链表将其反转。它目前不工作,我不知道为什么。到目前为止,我只用 C++ 编程,所以 C 中的细微差别真的让我陷入了循环。有人可以帮我找出程序中的错误吗?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct st_CharNode 
{
char theChar;
struct st_CharNode *next;
} CharNode;


void reverseIt( char *stringbuffer );


int main( int argc, char *argv[] )
{
char *stringBuffer;

//  Check number of user supplied arguments.  
if( argc != 2 )
{
    fprintf( stderr, "usage: %s string.  This reverses the string "
             "given on the command line\n" );
    exit( -1 );
}

// Copy the argument so we can make changes to it
stringBuffer = malloc( strlen(argv[1]) );
strcpy( argv[1], stringBuffer );

// Reverse the string
reverseIt( stringBuffer );

// Print the reversed string
printf( "the reversed string is '%s'\n", *stringBuffer );

return 0;
}


// Build a linked list backwards, then traverse it.

void reverseIt( char *stringbuffer )
{
CharNode *head, *node;
char *scan, *stop;

// initialize local vars
head = node = NULL;

// find the start and end of the string so we can walk it
scan = stringbuffer;
stop = stringbuffer + strlen(stringbuffer) + 1;

// walk the string
while (scan < stop)
{
    if (head == NULL)
    {
        head = malloc( sizeof(CharNode*) );
        head->theChar = *scan;
        head->next = NULL;
    }
    else
    {
        node = malloc( sizeof(CharNode*) );
        node->theChar = *scan;
        node->next = head;
        head = node;
    }
    scan++;
}

// Re-point to the buffer so we can drop the characters
scan = stringbuffer;

//  Traverse the nodes and add them to the string
while( head != NULL )
{
    *scan = head->theChar;
    free( head );
    node = head->next;
    head = node;
    scan++;
}

// Release head
free( head );   
}

当我 ./a.out 并在命令行上输入像“Hello”这样的字符串时,我的当前输出是“反转的字符串是'(null)'”。

4

2 回答 2

2

仅举几个问题...

分配不足

您没有考虑 C 字符串所需的终止 nulchar。

这个:

stringBuffer = malloc( strlen(argv[1]) );

应该是这样的:

stringBuffer = malloc( strlen(argv[1]) + 1);

错误的复印方向

分配后,您立即从新缓冲区中复制未初始化的数据,在顶部爆炸,argv[1]直到检测到 nulchar。更多未定义的行为。

这个:

strcpy( argv[1], stringBuffer );

应该是这样的:

strcpy( stringBuffer, argv[1] );

传递给 Printf 的取消引用不正确

"%s"格式说明符要求将一个以nulchar 结尾的字符串的地址作为匹配的可变参数传递。您正在传递*stringBuffer,即一个字符值,由编译器提升为 an int,然后用作地址。更糟糕的是,因为它是一个可变参数函数,这对于代码来说是完全合法的,但对于run显然是未定义的行为。一个好的代码静态分析编译器会为你捕捉到这一点。

这个:

printf( "the reversed string is '%s'\n", *stringBuffer );

应该是这样的:

printf( "the reversed string is '%s'\n", stringBuffer );

所有这些甚至都没有进入实际的反转功能。至少修复这些。您不需要(实际上会很疯狂)使用链表来反转 C 字符串。它可以通过两个指针和一个循环(或一个指针和一个索引)来完成,因此剖析该函数似乎适得其反。反转字符串实际上就是这么简单(并且到位):

void reverse_str(char *str)
{
    if (!str || !*str || !*(str+1))
        return;

    char *rhs = str + strlen(str) - 1;
    while (str < rhs)
    {
        char tmp = *str;
        *str++ = *rhs;
        *rhs-- = tmp;
    }
}
于 2013-10-24T02:51:05.397 回答
2

最大的错误是在排队

strcpy( argv[1], stringBuffer );

语法是

strcpy( char* destination, char* source );

你显然把两者颠倒了。

您还需要确保在到达 nul 字符之前停止 - 您可以通过将stop变量设置为比当前值小一的值来执行此操作:

stop = stringbuffer + strlen(stringbuffer) ;

当你打印出字符串时,你需要给printf函数正确的参数(一个指向字符串的指针):

printf( "the reversed string is '%s'\n", stringBuffer );

最后-感谢@WhozCraig-您需要为缓冲区分配更多内存以解决终止的`'\ 0':

stringBuffer = malloc( strlen(argv[1])) + 1 );

综上所述,以下是工作代码(包括一些调试 printf 语句——当你试图弄清楚发生了什么时,这总是一个好主意:

#include <stdlib.h>
#include <string.h>
typedef struct st_CharNode
{
char theChar; 
struct st_CharNode *next;
} CharNode;


void reverseIt( char *stringbuffer );


int main( int argc, char *argv[] )
{
char *stringBuffer;

//  Check number of user supplied arguments.
if( argc != 2 )
{
    fprintf( stderr, "usage: %s string.  This reverses the string "
             "given on the command line\n" );
    exit( -1 );
}

// Copy the argument so we can make changes to it
stringBuffer = malloc( strlen(argv[1]) + 1 );
strcpy( stringBuffer, argv[1]);

// Reverse the string
reverseIt( stringBuffer );

// Print the reversed string
printf( "the reversed string is '%s'\n", stringBuffer );

return 0;
}   

// Build a linked list backwards, then traverse it.

void reverseIt( char *stringbuffer )
{
CharNode *head, *node;
char *scan, *stop;

// initialize local vars
head = node = NULL;
printf("reversing '%s'\n", stringbuffer);

// find the start and end of the string so we can walk it
scan = stringbuffer;
stop = stringbuffer + strlen(stringbuffer) ;

// walk the string
while (scan < stop)
{
    printf("character: %c\n", *scan);
    if (head == NULL)
    {
        head = malloc( sizeof(CharNode*) );
        head->theChar = *scan;
        head->next = NULL;
    }
    else
    {
        node = malloc( sizeof(CharNode*) );
        node->theChar = *scan;
        node->next = head;
        head = node;
    }
    scan++;
}

// Re-point to the buffer so we can drop the characters
scan = stringbuffer;
printf("==== now reversing:====\n");
//  Traverse the nodes and add them to the string
while( head != NULL )
{
    *scan = head->theChar;
    printf("character: %c\n", *scan);
    free( head );
    node = head->next;
    head = node;
    scan++;
}
*stop = 0; // add the terminating nul
// Release head
free( head );
}
于 2013-10-24T02:55:09.723 回答