所以我试图编写一个从命令行接收字符串的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)'”。
答案 0 :(得分: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终止的字符串的地址作为匹配的variadic参数传递。您正在传递*stringBuffer
,即字符值,由编译器提升为int
,然后用作地址。更糟糕的是,因为它是一个可变函数,这对于代码来说是完全合法的,但显然是运行的未定义行为。一个好的代码静态分析编译器会为你捕获这个。
此:
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;
}
}
答案 1 :(得分: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 );
}