简体   繁体   English

在C中查找没有递归的字符串长度

[英]Find String Length without recursion in C

#include<stdio.h>
#include<conio.h>
void main()
{
    int str1[25];
    int i=0;
    printf("Enter a string\n");
    gets(str1);
    while(str1[i]!='\0')
    {
        i++;
    }
    printf("String Length %d",i);
    getch();
    return 0;
}

i'm always getting string length as 33. what is wrong with my code. 我总是得到的字符串长度为33。我的代码有什么问题。

That is because, you have declared your array as type int 这是因为,您已将数组声明为int类型

int str1[25]; 

^^^-----------Change it to `char`

You don't show an example of your input, but in general I would guess that you're suffering from buffer overflow due to the dangers of gets() . 您没有显示输入示例,但总的来说,我会因为gets()的危险而gets()缓冲区溢出。 That function is deprecated, meaning it should never be used in newly-written code. 该函数已弃用,这意味着它永远不应该在新编写的代码中使用。

Use fgets() instead: 使用fgets()代替:

if(fgets(str1, sizeof str1, stdin) != NULL)
{
  /* your code here */
}

Also, of course your entire loop is just strlen() but you knew that, right? 另外,当然,您的整个循环只是strlen()但您知道吗?

EDIT : Gaah, completely missed the mis-declaration, of course your string should be char str1[25]; 编辑 :Gaah,完全错过了错误声明,当然您的字符串应该是char str1[25]; and not int . 而不是int

So, a lot of answers have already told you to use char str1[25]; 因此,很多答案已经告诉您使用char str1[25]; instead of int str1[25] but nobody explained why. 而不是int str1[25]但没人解释原因。 So here goes: 因此,这里去:

A char has length of one byte (by definition in C standard). 一个char长度为一个字节(根据C标准的定义)。 But an int uses more bytes (how much depends on architecture and compiler; let's assume 4 here). 但是一个int使用更多的字节(多少取决于体系结构和编译器;在此假设4)。 So if you access index 2 of a char array, you get 1 byte at memory offset 2, but if you access index 2 of an int array, you get 4 bytes at memory offset 8. 因此,如果访问char数组的索引2,则在内存偏移2处获得1个字节,但是如果访问int数组的索引2,则在内存偏移8处获得4个字节。

When you call gets (which should be avoided since it's unbounded and thus might overflow your array), a string gets copied to the address of str1 . 调用gets (由于它是无界的,因此可能会导致数组溢出),应避免将其复制到str1的地址。 That string really is an array of char . 该字符串确实是char的数组。 So imaging the string would be 123 plus terminating null character. 因此,将字符串成像为123加上终止的空字符。 The memory would look like: 内存如下所示:

Adress:    0    1    2    3
Content:  0x31 0x32 0x33 0x00

When you read str1[0] you get 4 bytes at once, so str1[0] does not return 0x31, you'll get either 0x00333231 (little-endian) or 0x31323300 (big endian). 当您读取str1[0]您一次获得4个字节,因此str1[0]不返回0x31,您将得到0x00333231(小端)或0x31323300(大端)。

Accessing str1[1] is already beyond the string. 访问str1[1]已经超出字符串。

Now, why do you get a string length of 33? 现在,为什么会得到33的字符串长度? That's actually random and you're "lucky" that the program didn't crash instead. 实际上,这是随机的,您“很幸运”该程序没有崩溃。 From the start address of str1 , you fetch int values until you finally get four 0 bytes in a row. str1的起始地址开始,您将获取int值,直到最终连续获得四个0字节。 In your memory, there's some random garbage and by pure luck you encounter four 0 bytes after having read 33*4=132 bytes. 在您的内存中,有一些随机垃圾,而且很幸运,您在读取33 * 4 = 132字节后会遇到四个0字节。

So here you can already see that bounds checks are very important: your array is supposed to contain 25 characters. 因此,在这里您已经可以看到边界检查非常重要:您的数组应该包含25个字符。 But gets may already write beyond that (solution: use fgets instead). 但是gets可能已经超出此范围了(解决方案:改用fgets )。 Then you scan without bounds and may thus also access memory well beyond you array and may finally run into non-existing memory regions (which would crash your program). 然后,您将进行无限制的扫描,因此也可能会访问超出数组范围的内存,并最终可能会遇到不存在的内存区域(这将使程序崩溃)。 Solution for that: do bounds checks, for example: 解决方案:进行边界检查,例如:

// "sizeof(str1)" only works correctly on real arrays here,
// not on "char *" or something!
int l;
for (l = 0; l < sizeof(str1); ++l) {
    if (str1[l] == '\0') {
      // End of string
      break;
    }
}

if (l == sizeof(str1)) {
  // Did not find a null byte in array!
} else {
   // l contains valid string length.
}

I would suggest certain changes to your code. 我建议对您的代码进行某些更改。

1) conio.h 1)conio.h

    This is not a header that is in use. So avoid using it. 

2) gets 2)得到

    gets is also not recommended by anyone. So avoid using it. Use fgets() instead

3) int str1[25] If you want to store a string it should be 3)int str1 [25]如果要存储字符串,则应为

     char str1[25]        

The problem is in the string declaration int str1[25] . 问题出在字符串声明int str1[25] It must be char and not int 它必须是char而不是int

char str1[25]
void main() //"void" should be "int"
{
    int str1[25]; //"int" should be "char"
    int i=0;
    printf("Enter a string\n");
    gets(str1);
    while(str1[i]!='\0')
    {
        i++;
    }
    printf("String Length %d",i);
    getch();
    return 0;
}

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

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