【问题标题】:Need to be "pointed" in the right direction beginning C programming开始 C 编程需要“指出”正确的方向
【发布时间】:2017-10-05 23:03:39
【问题描述】:

感谢您的宝贵时间。我提前道歉,我是 C 编程的新手,并在堆栈溢出上发帖。任何我可能遗漏的信息和您的问题请提出。

我有一个正在为我的班级工作的实验室,但我无法理解可怕的指针是如何工作的。首先我会解释一下实验说明。

首先,我要创建一个包含 200 个单词的数组,其中 null 的最大长度为 30+1。 接下来,调用我需要创建的函数,包括:

  1. 一个读取函数,将文件中的单词读入数组。我必须使用 fopen 和 fscanf 函数。
  2. 使用每个字符的 ASCII 码将字符串转换为小写的函数。 (必须使用指针)
  3. 返回字符串长度的函数。(不能使用strlen函数,必须使用指针)
  4. 具有三个参数的函数(单词数组、数组中的单词数和一个 int 长度)。函数返回数组中匹配 int 长度的单词数。
  5. 打印函数,用于打印数组中的所有单词。

我使用的 IDE 是 Dev C++,它很不稳定,所以我也一直在使用 netbeans。 我只尝试创建读取、打印和转换为小写的函数。我首先尝试读取文件并在 main.xml 中打印数组。我正在阅读的文件是由我创建的,它包含一个简短的句子:

  • 这里有很多字

编辑- 将主代码更新为当前代码,在 main 中使用小写循环。

#define rows 200    //How many words allowed in array.
#define cols 31     //How many characters allowed for each word.

void lowercase(char* words, int count);
int read(char (*words)[cols]);
void print(char (*words)[31], int count);

int main(int argc, char *argv[]){
    char words[rows][cols];
    int i, j;   
    int count = read(words);

    print(words, count);
/*
    //make words lowercase
    for(i = 0;i<count;i++){
        for(j = 0;j<cols;j++){
            if(words[i][j]!=0){
                if(words[i][j]<91 && words[i][0]>64)
                    words[i][j] = words[i][j]+32;
            }
        }
    }*/

    for(i = 0;i < count;i++){
        lowercase(*words+i, count);
    }
    print(words, count);

    return 0;
}

代码写得不好,管理得当我只是想先让一切正常工作,然后它会更合适。第一个 printf 输出应该是这样的:

数组[0]:那里

数组 [1]: 是

数组[2]:所以

数组 [3]:很多

数组 [4]:单词

数组[5]:在

数组 [6]:这里

然后我的打印函数正确地打印出数组中的单词,但它包含每个单词的所有 30 个空格,而不仅仅是单词。是这样写的,我需要改一下。

void print(void *array, int SIZE){
    int i,
        j;

    char *charArray = (char *) array;

    for( j = 0; j < SIZE; j++ ){
        for( i = 0; i < SIZE; i ++){
            printf( "%c ", charArray[j*SIZE + i] );
        }
        printf( "\n" );
    }
}

我创建的 tolower 函数部分地将每个单词的第一个字母转换为小写。现在它坏了,不记得我改变了什么。

EDIT- 更新小写函数。 main 中的小写字母完全可以使用,但使用此函数时,它不会将所有单词都转换为小写字母,它会在第三个单词处停止,其余的都是相同的。

void lowercase(char *words, int count){
    int j;

    for(j = 0;j<cols;j++){
        if(words[j]!=0){
            if(words[j]<91 && words[j]>64)
                words[j] = words[j]+32;
        }
    }
}

我试图将 main 中的读取代码移动到它自己的函数中,也试图用指针模仿打印代码,但是当我运行程序时它停止并且 exe 文件停止工作窗口弹出命令提示符。 IDE 中没有错误或警告。

int read(void *array){
    FILE *file;
    int i,
        j;

    char *words = (char *) array;
    file = fopen("words.txt", "r");
    //STORE IN ARRAY
    for(i=0;i<7;i++)
        fscanf(file,"%s", words[i]);
}

如果您还没有弄清楚,我不知道何时或如何使用指针或地址。我在 12 个小时内基本上学会了所有的 C 语言,在我看来,这根本没有足够的时间来学习这门语言,尤其是有效地理解它。任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 为什么使用void*而不是char words[][31];char (*words)[31];
  • 我不是想搞笑,但这个视频很棒。帮助我更好地理解它。 youtube.com/watch?v=mnXkiAKbUPg
  • @BLUEPIXY 这似乎是让它工作的唯一方法我会得到一堆使用 char 的错误。不理解指针或 C 显示的错误无济于事。我的教授希望我使用指针而不是数组括号。
  • 如果您的函数仅接收void* 的第一个地址(作为指针),则另一个参数需要列的大小。同样在print中,列大小也被用作行数,但这显然是错误的。
  • 是的,除非您对数组大小使用 global 常量(或提供一个 sentinel 标记数组中已填充元素的结尾),然后当您将数组的大小传递给任何函数时。为什么?因为当作为参数传递给函数时,第一级间接转换为指针。没有办法根据指向数组的指针来确定数组的大小。因此,您将元素数作为参数传递,以提供指针指向的元素数。例如words[200][31] 作为(*words)[31] 传递,所以你必须传递其余部分。

标签: c arrays function pointers multidimensional-array


【解决方案1】:

像这样修复:

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

//Stringification
#define S_(n) #n
#define S(n) S_(n)

//Information to be shared across the whole area
#define MAX_ROWS 200
#define MAX_WORD_LENGTH 30
#define COLS (MAX_WORD_LENGTH + 1)

#define DATA_FILE "words.txt"

int read(void *array);
void print(void *array, int rows);

int main(void){
    char words[MAX_ROWS][COLS];
    int rows;

    rows = read(words);
    print(words, rows);

     return 0;
}

int read(void *array){
    FILE *file = fopen(DATA_FILE, "r");
    if(file == NULL){
        perror("fopen:");
        exit(EXIT_FAILURE);
    }
    char *words = array;
    int rows;
    for(rows = 0; rows < MAX_ROWS; ++rows, words += COLS){
        if(fscanf(file, "%" S(MAX_WORD_LENGTH) "s", words) == EOF)
            break;
    }
    fclose(file);
    return rows;
}

void print(void *array, int rows){
    char *words = array;
    for(int r = 0; r < rows; ++r, words += COLS){
        printf("Array [%d]: %s\n\n", r, words);
    }
}

【讨论】:

  • @M.M 确实如此。谢谢
  • 使用全局信息不是一个好方法,因为它会损害功能独立性。
【解决方案2】:

通过将二维数组转换为char*,您丢失了一些信息。如果您正确读取了单词,那么在内存中,您的数组可能如下所示:

0         10        20        30
|.........|.........|.........|.
There
ARE
so
MANY
words
in
HERE

要访问words[1],编译器会自动从数组的开头偏移 31 个字节。

您的问题是,在将words 转换为char* 之后,编译器不再知道二维结构,words[1] 现在只会从数组的开头偏移 1 个字节。

一个简单的解决方案是重新定义您的 read 函数:

int read(char words[][31])
{
    FILE *file;
    int i, j, count = 0;
    file = fopen("words.txt", "r");
    for (i=0; i<7; i++)
    {
        count += (1 == fscanf(file, "%s", words[i]));
    }
    return count;
}

现在编译器知道words[i] 的内存步长是31 个char 值。

print类似:

void print(char words[][31], int count)
{
    int i;
    for( i = 0; i < count; i ++)
    {
        printf( "%s\n", words[i] );
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-27
    • 2015-11-22
    • 1970-01-01
    • 2018-03-23
    • 2021-03-21
    • 2018-07-02
    相关资源
    最近更新 更多