For循环中每个数组元素[i]都被赋值,为什么数组没有填入值?

Why array does not filled with values while For loop, in which each array element[i] is assign with variable?

代码编译正常。我尝试使用调试器,但无法找出问题所在。 每次迭代“c”都被填充,但似乎我尝试将此变量“c”分配给数组的方式没有任何反应,因此结束打印语句以“ciphertext:EMPTY NOTHING”

非常欢迎任何帮助或想法。我正在上课并尝试解决一组问题。我只是初学者,请不要评判:)

#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>

int main (int argc, string argv[])
{

    if(argc < 2 || argc<2 )
    {
        printf("Usage: ./caesar key \n");
        return 1;
    }
    
   
    else if(argc == 2)
    {
        for (int i = 0; i < strlen(argv[1]); i++)
        {
            if(!isdigit(argv[1][i]))
            {
                printf("Usage: ./caesar key \n");
                return 1;
            }
        }
    }



    int key = atoi(argv[1]);


    string initial_text = get_string("plaintext: ");

    
    int cipher[strlen(initial_text)];
    int i = 0;
    int n = strlen(initial_text);

    for (i = 0; i < n; i++)
    {
        int c = 0;

        if (isupper(initial_text[i]))
        {
            c = (((int)initial_text[i] - 65 + key) % 26) + 65;
            cipher[i] += c;
        }

        else if (islower(initial_text[i]))
        {
            c = (((int)initial_text[i] - 97 + key) % 26) + 97;
            cipher[i] += c;
        }

        
        else
        {
            c=initial_text[i];
            cipher[i] += c;
        }
    }

    //////////////////
    printf("ciphertext: %c\n", (char)cipher);

}

存在一些问题:

  1. 当您[可能]想要char.
  2. 时,将int用于cipher
  3. cipher 中没有为尾随的 0x00 [EOS] 字符串终止符定义足够的 space
  4. 不是设置最后的EOS。
  5. printf 中使用 %c 而不是 %s
  6. if ((argc < 2) || (argc < 2))是错误的,可以用if (argc != 2)代替。
  7. 因为 if 做了 return,所以不再需要后续的 else if 检查。
  8. “硬接线”十进制 值(例如 65 代表 'A')。
  9. for 循环的条件表达式中使用 strlen。这将循环的 运行 时间从 O(n) 增加到 O(n^2)。
  10. 这可以替换为(例如)将数组元素与 0x00 进行比较。
  11. 使用strtol代替atoi并检查结束可以在单个操作中进行解码验证。
  12. 定义 argv 时不要使用 string -- 使用 char **argv.
  13. 您的 main 末尾缺少 return 0;
  14. 有很多重复的代码可以简化。

这是重构后的代码:

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

// I don't have cs50 handy, so a quick hack ...
#define string  char *
string
get_string(const char *prompt)
{
    char buf[1000];
    char *cp;

    printf("%s",prompt);
    fflush(stdout);

    do {
        cp = fgets(buf,sizeof(buf),stdin);
        if (cp == NULL)
            break;

        // strip newline
        buf[strcspn(buf,"\n")] = 0;

        // IIRC, [real] get_string does heap allocation (vs. static buffer) but
        // for demo purposes here, doesn't really matter
        cp = strdup(buf);
    } while (0);

    return cp;
}

int
main(int argc, char **argv)
{

    // check if there is exactly 2 arguments passing, otherwise prompt for a
    // valid key(+return 1, to signal mistake)
    if (argc != 2) {
        printf("Usage: ./caesar key \n");
        return 1;
    }

    // otherwise check if the key is only a digit and prompt for a valid
    // key(+return 1, to signal mistake)
    // loop through each character in the second argument and validate
    char *arg = argv[1];

    // convert a string to int variable to be used in transformation of letters
    int key = strtol(arg,&arg,10);
    if (*arg != 0) {
        printf("Usage: ./caesar key \n");
        return 1;
    }

    // prompt for plaintext
    string initial_text = get_string("plaintext: ");

    // create an array of int to store encrypted letters to then be converted
    // in print by (char)
    // NOTE: we need one extra to make room for the trailing EOS
    char cipher[strlen(initial_text) + 1];

    const char *src = initial_text;
    char *dst = cipher;

    for (int chr = *src++;  chr != 0;  chr = *src++, ++dst) {
        if (isupper((unsigned char) chr)) {
            *dst = (((chr - 'A') + key) % 26) + 'A';
            continue;
        }

        if (islower((unsigned char) chr)) {
            *dst = (((chr - 'a') + key) % 26) + 'a';
            continue;
        }

        // for all none alphabetic symbols leave them as they are
        *dst = chr;
    }

    // set the trailing EOS
    *dst = 0;

    // ////////////////
    printf("ciphertext: %s\n", cipher);

    return 0;
}

你可以这样写

if ( argc < 2 || argc<2 || argc < 2 )

而不是

if ( argc < 2 || argc<2 )

这是正确的,但没有意义。

随便写

if ( argc != 2 )
{
    puts( "Usage: ./caesar key" );
    return 1;
}

这条else语句

else if(argc == 2)

是多余的。删除它。

而不是这个 for 循环

for (int i = 0; i < strlen(argv[1]); i++)
{
    if(!isdigit(argv[1][i]))
    {
        printf("Usage: ./caesar key \n");
        return 1;
    }
}

写起来更简单

char *p;
unsigned long ley = strtoul( argv[1], &p, 10 );

if ( *p || key == ULLONG_MAX )
{
    puts( "Usage: ./caesar key" );
    return 1;   
}

无需定义变长数组。您可以更改指针 initial_text.

指向的原始字符串

引入变量n是多余的

int n = strlen(initial_text);

而不是循环

for (i = 0; i < n; i++)

你可以使用这个循环

for ( size_t i = 0; initial_text[i] != '[=18=]'; i++ )

而不是这些 if 语句

if (isupper(initial_text[i]))

else if (islower(initial_text[i]))

写起来会更安全

if ( isupper( ( unsigned char )initial_text[i]))

else if ( islower( ( unsigned char )initial_text[i] ) )

同时使用像 65 这样的幻数会使代码变得不可读。例如你可以

c = ( initial_text[i] - 'A' + key ) % ( 'Z' - 'A' + 1 ) + 'A';

c = ( initial_text[i] - 'a' + key ) % ( 'z' - 'a' + 1) + 'a';

and 而不是复合赋值运算符

cipher[i] += c;

你需要写

initial_text[i] = c;

此外,在 printf 的调用中,您使用了不正确的转换说明符 %c 和转换

printf( "ciphertext: %c\n", (char)cipher);

因为字符串应该就地更新,所以 printf 的调用看起来像

printf( "ciphertext: %s\n", initial_text );