在C语言中,在for循环的声明部分声明str[i]=' '来获取最后一个字符'i'的值是错误的吗?

问题描述 投票:0回答:3

我尝试编写代码来反转字符串,但没有计算字符串的长度。

我输入后,它显示分段错误,请帮忙...

#include <stdio.h>

int main() {
  char nor[10], rev[10];
  int i, d = 0, j;
  printf("enter\n");
  scanf("%s", nor);
  for (i = 0; nor[i] != '\0'; i++) {
    for (nor[j] = '\0'; j < 10; j--) {
      if (i == d)
        rev[i] = nor[j];
      d++;
    }
  }
  puts(rev);
  return 0;
}

我试图在字符串结束的地方获取j的值,所以在内部for循环中我提到了

nor[j]='\0'
,但似乎这是破坏代码的部分,但我给出的逻辑看起来很好我。

c for-loop reverse c-strings
3个回答
2
投票

在内部 for 循环中

for (nor[j] = '\0'; j < 10; j--) {

最初

j
具有不确定值,因为它未初始化

int i, d = 0, j;

作业

nor[j] = '\0'

已经调用未定义的行为。

请记住,使用转换规范

"%s"
是不安全的。用户可以覆盖用作此类转换规范的参数的字符数组。

并且还使用变量

d
没有任何意义。变量
d
只是多余的。

在不知道字符串长度的情况下无法反转字符串。

所以首先需要确定字符串的长度,然后对字符串进行反转。

请注意,您并不是试图反转字符串。您正在尝试以相反的顺序复制另一个字符数组中的字符串。

如果你想反转一个字符串,那么程序可以如下所示。

#include <stdio.h>

int main( void ) 
{
    char nor[10];

    printf( "Enter a string: " );
    
    if ( scanf( "%9s", nor ) == 1 )
    {
        size_t n = 0;
        while ( nor[n] != '\0' ) ++n;

        for ( size_t i = 0; i < n / 2; i++ )
        {
            char c = nor[i];
            nor[i] = nor[n - i - 1];
            nor[n - i - 1] = c;
        } 

        puts( nor );
    }

    return 0;
}

如果你想将一个字符串以相反的顺序从一个字符数组复制到另一个字符数组,那么程序可以如下所示:

#include <stdio.h>

int main( void ) 
{
    char nor[10], rev[10];

    printf( "Enter a string: " );

    if ( scanf("%9s", nor ) == 1 )
    {
        size_t n = 0;

        while ( nor[n] != '\0' ) ++n;
        
        rev[n] = '\0';

        for ( size_t i = 0; n-- != 0; i++ )
        {
            rev[i] = nor[n];
        }
  
       puts( rev );
    }

    return 0;
}

2
投票

删除任何不涉及

j
变量的行,剩下的就是:

int i, d = 0, j;
// ...
for (nor[j] = '\0'; j < 10; j--)

j
从未在任何地方分配过值 - 因此它包含一些任意垃圾值,很可能由于访问超出其范围的数组而引发未定义的行为,从而导致给定情况下崩溃(但情况不一定如此,只是任何事情都可能发生在 UB 上,程序立即崩溃,在后来某个看似完全不相关的时间点崩溃,运行但表现出奇怪的行为或看起来运行良好)。

旁注:用户输入太长的数据可能会引发类似的情况,因为您在扫描输入时没有阻止这种情况(特别是当您的数组非常短时)。为了安全起见,请尝试

scanf("%9s", nor)

然后,为了反转,无论如何都不需要嵌套循环,而是需要两个单独的循环;第一个用于查找字符串的末尾,第二个用于执行实际的反转,可能如下所示:

char* n = nor;
while(*n)
{
    ++n;
}
// now n points to the end of the string

for(char* r = rev; n-- != nor; ++r)
//                 ^ check first, then decrement:
//                   we are behind current character to copy
//                   once we are equal there are no characters left
{
    *r = *n;
}
*r = 0; // terminate the reversed string

编辑(受到Vladanswer的启发;不过,使用指针对我来说显得更优雅):

您甚至可以恢复就地,从而完全删除第二个数组:

char* n = nor;
while(*n)
{
    ++n;
}
--n; // don't want to include the null terminator in reversal
for(char* r = nor; r < n; ++r, --n)
{
    char c = *r;
    *r = *n;
    *n = c;
}
// null terminator remained untouched anyway, so no action necessary

但请注意,除了(内)相等之外的任何指针比较只有在两个指针都指向同一个数组时才是合法的,当然,这里就是这种情况......

编辑(受到问题评论的启发):单个迭代变体(需要两个缓冲区)。

如果您只想迭代一次,您可以从目标缓冲区的末尾填充:

char* r = rev + sizeof(rev);
*--r = 0;
for(char* n = nor; *n; ++n)
{
    *--r = *n;
}
// r now points to the begin of the reverted string...

(如果您坚持使用索引进行操作:将

i
初始化为
0
,将
j
初始化为
sizeof(rev)
,并使用这些进行与上面相同的操作;然后您将在
rev + j
处找到恢复的字符串)。


1
投票

我认为这是一个非常有趣的问题。 首先,

nor[j] = '\0'
线有问题。 我会尽力解释一下。
j
有什么价值?如果您这样做
nor[j] = '\0'
j
将不会从
nor[]
数组中获取最后一个元素的索引。
nor[j] = '\0'
表示在
nor[]
数组中,在
j
位置处要放置
'\0'
。 我认为你遇到了分段错误,因为当你在此处声明没有值的
j
时,它会采用一个随机值,例如571239。因此,当你执行
int i, d = 0, j;
时,你想从
访问第571239个位置nor[j]='\0'
不存在的数组。
所以回答你的问题,是的,在 for 循环的声明部分声明 

nor[]

来获取最后一个字符处

str[i]='\0'
的值是错误的。
    

© www.soinside.com 2019 - 2024. All rights reserved.