0

首先,我要感谢大家为我所做的一切,无论他们是否知道。我是第一次海报长期潜伏者。

我正在开始一个基于 C 及其几个变体的新课程。问题是它假设你至少有 C++ 的经验,不幸的是我只学了几个学期的 Java 和 Mips。我现在正在努力学习 C,没有任何书籍或课程计划。我使用 Google 度过了第一个月。但是我今天的问题似乎无法解决,虽然我知道这是基本的,但我希望在理解我的作业中代码的工作方面得到一些帮助。

教授为我们提供了以下代码:

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

void encrypt(int offset, char *str) {

    int i,l;

    l=strlen(str);

    printf("\nUnencrypted str = \n%s\n", str);

    for(i=0;i<l;i++)
        if (str[i]!=32)
            str[i] = str[i]+ offset;

    printf("\nEncrypted str = \n%s \nlength = %d\n", str, l);
}   

void decrypt(int offset, char *str) {


}   

void main(void) {

    char str[1024];

    printf ("Please enter a line of text, max %d characters\n", sizeof(str));

    if (fgets(str, sizeof(str), stdin) != NULL)
    {
        encrypt(5, str);    // What is the value of str after calling "encrypt"?

        // add your method call here:
    }
}   

因此,作业的问题在代码中列出,但要明确这不是我所追求的。我想了解这个程序到目前为止是如何工作的。

具体来说:

  1. 为什么写char str[1024]

  2. 究竟在if (fgets(str, sizeof(str), stdin) != NULL)做什么?我有一个不错的想法,但我不知道它背后的原因。

3.最后(我希望)在

if (str[i]!=32)
    str[i] = str[i]+ offset;

为什么我们担心str[i]不等于 32?

如果有很多问题,我很抱歉,但我真的很想了解这一点。

另外,如果您知道 C 的任何精彩读物,请告诉我,因为此时我相当担心本学期的剩余时间。

编辑:

只是想非常感谢所有回答我的人。不幸的是,我不是那些立即喜欢继续提出更多问题以承认您帮助了我的人之一。所以对于那些我没有直接感谢或评论的人,非常感谢。现在,我对 30 分钟前还感到紧张的一些非常基本的概念有了更牢固的把握。

4

5 回答 5

2
  1. 您使用char str[1024]C 是因为 C 没有任何字符串的概念,只有char由 NUL aka 0 终止的数组。它没有任何您自己没有明确实现的“可拉伸”容器的概念。因此,如果您想在不编写大量自己的输入处理的情况下读取输入字符串,您可以猜测某个最大长度(在本例中为 1024)并提前为此腾出空间。
  2. fgets读取一个字符串(当您在 C 中说“字符串”时,这意味着“char由 0 终止的数组,如上所述)。您传入strwhich 是指向存储开始的指针,并且sizeof(str)在编译时将其评估为数字str占用的字节数。这意味着1024在这种情况下,如果您更改行,它将跟踪更改char str。该参数阻止fgets写入超出分配的空间str。请记住,它不是一个有弹性的字符串。
  3. ASCII 32 是空格。写起来会更清楚str[i] != ' '
于 2012-09-17T02:07:18.690 回答
2

Kernighan + Ritchie 的书The C Programming Language将是一个很好的开始。
亚马逊:这里

另请参阅权威 C 书籍指南和列表

于 2012-09-17T02:16:22.643 回答
0
  1. 这表示这str是一个 1024char秒的数组
  2. “fgets() 从流中最多读取一个小于 size 的字符并将它们存储到 s 指向的缓冲区中。在 EOF 或换行符之后停止读取。如果读取换行符,则将其存储到缓冲区中。终止空字节 ('\0') 存储在缓冲区中的最后一个字符之后。"
  3. 显然,值为 32 的字符不应“加密”。找一张 ASCII 表,看看 32 是什么特殊字符...

附言。“gets() 和 fgets() 在成功时返回 s,在错误时或在未读取任何字符时出现文件结尾时返回 NULL。”

于 2012-09-17T02:03:18.113 回答
0
char str[1024];

声明str为 1024 个元素的数组char

fgets(str, sizeof (str), stdin)

从(标准输入,基本上是您的控制台)读取多达sizeof (str)(1024) 个字符stdin并将这些字符存储到str. fgets如果在读取过程中出现错误,将返回 NULL,所以

if (fgets(std, sizeof(str), stdin) != NULL)
{
  encrypt(...);
  ...
}

if仅当我们成功读取输入字符串时才会执行语句的主体。

32是空格 ( ' ') 字符的 ASCII 码;无论出于何种原因,加密算法都会在字符串中保留空格字符。

于 2012-09-17T02:11:54.607 回答
0

第一个问题:

在 Java 中,您必须拥有new所有数组,例如char[] arr = new char[1024]. 在 C(和 C++)中,您可以选择像 Java 一样动态分配数组(malloc在 C 和new []C++ 中使用),或者使用固定大小(char str[1024]您在此处看到)静态分配数组。

在 C 语言中,因为所有内存都需要手动管理mallocand free,所以静态分配的缓冲区会节省一些麻烦,因为它们会在函数退出时自动释放。在 Java 中,您很少处理内存分配,因为运行时会自动垃圾收集未使用的对象。

在 Java 中,你有String,它包装了一个char. 在 C 中,您只有 char 数组,通常表示为第一个字符 ( )的数组char或指针。char *还要注意,Javachar在处理 Unicode 时是 16 位(2 个字节)宽;Cchar的大小只有 8 位(1 个字节)。

最后,请注意,在 C 中,所有字符串都以空字节结尾'\0'。因此,字符串必须足够大以容纳内容和终止的空字节——未能计算空字节可能会导致缓冲区溢出。

第二个问题:

在Java 中,您可以使用readLine从文件或用户输入中读取一行文本。在 C 中,您使用fgets. 然而,在 Java 中,运行时会动态分配一个足够大的字符串来容纳输入行(不管该行有多长);在 C 中,由于缓冲区通常由程序员分配,因此函数只能读取缓冲区允许的字符数(读取缓冲区末尾的字符称为缓冲区溢出,这是安全漏洞的常见原因)。

fgets因此需要三个参数:要读取的缓冲区、缓冲区的大小以及要从中读取的文件(此处stdin为控制台)。

第三个问题:

C 中的字符串是简单的 ASCII 字符序列。所以,只有当字符不是 32 时,代码才会加密字符(通过添加这个“偏移量”)——一个空格字符。结果是所有非空格都将被转换为乱码,而空格则完好无损。

于 2012-09-17T02:15:41.577 回答