关于C语法和工作的问题

时间:2012-09-17 01:57:32

标签: c

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

我正在开始一个基于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. 3.最后(我希望)

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

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

    我很抱歉,如果要提出这个问题,我真的很想明白这一点。

    另外,如果你知道C的任何精彩读物,请告诉我,因为我现在非常担心这个学期的剩余时间。

    编辑:

    我想非常感谢所有回答我的人。不幸的是,我不是那些立即想要继续提出更多问题来承认你帮助过我的人之一。对于那些我没有直接感谢或回复的人,非常感谢。我现在对30分钟前我感到紧张的一些基本概念有了更为坚定的把握。

5 个答案:

答案 0 :(得分:2)

  1. 您使用char str[1024]因为C没有任何字符串概念,只有char的数组由NUL又名为0终止。它没有任何“弹性”容器概念。没有明确地实现自己。因此,如果您想要读取一串输入而不需要编写大量自己的输入处理,那么您可以猜测某个最大长度(在这种情况下为1024),并提前为此腾出空间。
  2. fgets读取一个字符串(当你在C中说“string”时,意味着“char数组以0结尾,如上所述。)你传入str这是指向存储开始的指针和sizeof(str),它在编译时被评估为str占用的字节数。在这种情况下,它意味着1024,具有它的优势如果您更改char str行,则会跟踪更改。该参数阻止fgets写入超出str的分配空间。请记住,它不是一个有弹性的字符串。
  3. ASCII 32是空格。写str[i] != ' '
  4. 会更清楚

答案 1 :(得分:2)

一个很好的开始是Kernighan + Ritchie的书, The C Programming Language
亚马逊:here

另请参阅The Definitive C Book Guide and List

答案 2 :(得分:0)

  1. 这表示str是一个1024 char s
  2. 的数组
  3. “fgets()从流中读取最多一个小于大小的字符,并将它们存储到s指向的缓冲区中。读取在EOF或换行符后停止。如果读取换行符,则存储它在缓冲区中的最后一个字符之后存储一个终止空字节('\ 0')。“
  4. 显然,值为32的字符不会被“加密”。找到一个ASCII表,看看特殊字符32是什么......
  5. PS。 “gets()和fgets()成功返回s,错误时返回NULL或文件结束时没有读取任何字符。”

答案 3 :(得分:0)

char str[1024];

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

fgets(str, sizeof (str), stdin)

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

if (fgets(std, sizeof(str), stdin) != NULL)
{
  encrypt(...);
  ...
}
只有在我们成功读取输入字符串时,

才会执行if语句的主体。

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

答案 4 :(得分:0)

第一个问题:

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

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

在Java中,你有free,它包含一个String数组。在C中,您只有char数组,通常表示为char数组或指向第一个字符(char)的指针。另请注意,Java char *处理Unicode时为16位(2字节)宽; C char的大小只有8位(1字节)。

最后,请注意,在C中,所有字符串都以空字节char终止。因此,字符串必须足够大以容纳内容和终止空字节 - 无法计算空字节可能导致缓冲区溢出。

第二个问题:

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

fgets因此需要三个参数:要读入的缓冲区,缓冲区的大小以及要读取的文件(此处fgets,即控制台)。

第三个问题:

C中的字符串只是ASCII字符的序列。因此,只有当字符不是32 - 空格字符时,代码才会加密字符(通过添加此“偏移”)。结果是所有非空间都将被转换为乱码,使空间保持不变。