通过函数更改时,main中数组中的值不更新

时间:2018-11-04 05:56:49

标签: c

调用unsigned char[ ]函数后,我的程序似乎没有更新main中的changecontents,因为它为storage[13]输出的值与之前的值相同电话。但是,这不是我的全部代码-我将常规功能复制到了这里。

更新:对不起,我忘了指出data1 [13]已初始化-索引0到至少200包含值。

Update2:添加了readfile函数,用于初始化main中的data1。

Update3:检查了readfile中的fopen()函数是否返回了NULL; file.gif存在。

#include <stdio.h>
int main()
{
    unsigned char data1[4000] = {0};  
    readfile(data1, 4000, "file.gif");    // filled 3022 indices in data1; file.gif exists
    printcontents(data1);       // prints the array contents as desired here 
    changecolor(data1);     // doesn’t change the array contents 
    printcontents(data1);       // prints the same array contents as original      
    return 0;
}
int printcontents(unsigned char storage[ ])
{
    printf(“%X”, storage[13]);  // data1 passed in function call in main
    return 0;
}
int changecolor (unsigned char storage[ ])
{
    storage[13] = storage[13] >> 2;     // data1 passed in function call in main
    return 0;
}
int readfile(unsigned char storage[ ], int capacity, char filename[ ])
{
    FILE * content = fopen(filename, "r");
    if (content != NULL)
    {
        size_t numElements, bytesPer = sizeof(unsigned char);
        fseek(content, 0, SEEK_END);
        numElements = ftell(content);
        rewind(content);
        fread(storage, bytesPer, numElements, content);   // returned 3022
        fclose(content);
    }
    return 0;
}

3 个答案:

答案 0 :(得分:2)

更新后的代码未使用capacity中的readfile()。该函数无法打开文件时未明确报告错误-这花了我一些时间。

这是您代码的一种变体,可产生我期望的输出:

#include <stdio.h>
int printcontents(unsigned char storage[ ]);
int changecolor (unsigned char storage[ ]);
int readfile(unsigned char storage[ ], size_t capacity, char filename[ ]);
int main(void)
{
    unsigned char data1[4000] = {0};  
    readfile(data1, 4000, "file.gif");    // filled 3022 indices in data1; file.gif exists
    printcontents(data1);       // prints the array contents as desired here 
    changecolor(data1);     // doesn’t change the array contents 
    printcontents(data1);       // prints the same array contents as original      
    return 0;
}
int printcontents(unsigned char storage[ ])
{
    printf("%#X\n", storage[13]);  // data1 passed in function call in main
    return 0;
}
int changecolor (unsigned char storage[ ])
{
    storage[13] = storage[13] >> 2;     // data1 passed in function call in main
    return 0;
}
int readfile(unsigned char storage[ ], size_t capacity, char filename[ ])
{
    FILE * content = fopen(filename, "r");
    if (content != NULL)
    {
        size_t numElements, bytesPer = sizeof(unsigned char);
        fseek(content, 0, SEEK_END);
        numElements = ftell(content);
        if (numElements > capacity)
            numElements = capacity;
        rewind(content);
        if (fread(storage, bytesPer, numElements, content) != numElements)
            printf("Bogus input\n");    // returned 3022

        printf("Got %zu bytes\n", numElements);
        for (int i = 0; i < 16; i++)
            printf(" 0x%.2X", storage[i]);
        putchar('\n');
        fclose(content);
    }
    else
        fprintf(stderr, "failed to open file '%s'\n", filename);
    return 0;
}

我使用了随机数生成器来创建file.gif文件。当我在该文件上运行程序时,我得到了:

Got 3023 bytes
 0x62 0x66 0x74 0x77 0x76 0x62 0x66 0x6E 0x6D 0x72 0x70 0x62 0x63 0x66 0x71 0x7A
0X66
0X19

如您所见,数组位置13(0x63和0x71之间)的值从0x66(102)变为0x19(25),这是正确的“除以4”值。

不可能从这里猜测您的版本出了什么问题。最简单的猜测是文件file.gif不存在,尽管您的说法与此相反。您的代码未显示fread()成功。

我所做的大多数更改都是使代码通过默认的编译器警告所必需的。我正在Mojave 10.14.1上的XCode 10.1中使用clang,并使用以下命令将arr41.c编译为arr41

/usr/bin/clang -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
    -Wstrict-prototypes arr41.c -o arr41

我还添加了诊断代码,以在文件未打开时发出警告,并打印读取的数据量,该数据的前16个字节,并整理打印值的格式(以换行符结尾的输出) ,通常)。

我顺便指出,这不是MCVE(Minimal, Complete, Verifiable Example)。 MCVE可能是:

#include <stdio.h>

static void printcontents(unsigned char storage[]);
static void changecolor(unsigned char storage[]);

int main(void)
{
    unsigned char data1[20] = "ABCDEFGHIJKLMNOPQRS";
    printcontents(data1);
    changecolor(data1);
    printcontents(data1);
    return 0;
}

static void printcontents(unsigned char storage[])
{
    printf("%#X\n", storage[13]);
}

static void changecolor(unsigned char storage[])
{
    storage[13] = storage[13] >> 2;
}

输出:

0X4E
0X13

同样,这显然是正确的。

答案 1 :(得分:2)

您的问题是验证之一,通常是新程序员的事后思考,但实际上,这应该是您的编码方法的主要重点。您显示的代码(以及在您更新和替换 [1] 问题中的原始代码之前所使用的代码)对以下任何一项进行了零验证程序进行必要的函数调用。

即使添加了检查if (content != NULL)之后,您也无法判断该代码是否已执行,或者您的函数只是返回了0,因为在失败时没有诊断输出,并且您也没有有意义地使用从readfile返回(无论成功还是失败-它总是只返回0

为每个函数选择一个有意义的返回类型。如果您不需要利用函数的返回值,请将该函数键入void

添加有意义的返回类型和值将准确确定程序失败的位置。例如,提供有意义的回报并完全验证您的代码,您可以执行以下操作:

#include <stdio.h>

#define FNAME "file.gif"    /* if you need constants, #define one (or more) */
#define MAXC 4000

/* select proper/meaningful return types for your functions */
void printcontents (const unsigned char *storage);
void changecolor (unsigned char *storage);
int readfile (unsigned char *storage, int capacity, char *filename);

int main (void) {

    unsigned char data1[MAXC] = {0};  

    if (!readfile(data1, MAXC, FNAME))  /* validate all necessary calls */
        return 1;

    printcontents(data1);
    changecolor(data1); 
    printcontents(data1);

    return 0;
}

void printcontents (const unsigned char *storage)
{
    printf("%X", storage[13]);
}

void changecolor (unsigned char *storage)
{
    storage[13] >>= 2;
}

int readfile (unsigned char *storage, int capacity, char *filename)
{
    size_t numElements, bytesPer = sizeof(unsigned char);
    FILE *content = fopen (filename, "r");

    if (!content) {
        perror ("fopen-filename");
        return 0;
    }
    if (fseek (content, 0, SEEK_END) == -1) {
        perror ("fseek-content");
        return 0;
    }

    if ((long)(numElements = ftell(content)) == -1) {
        perror ("ftell-content");
        return 0;
    }

    rewind(content);

    if (numElements > capacity * bytesPer)
        fprintf (stderr, "warning - file size exceeds read capacity.\n");

    if (fread (storage, bytesPer, numElements, content) != numElements) {
        fprintf (stderr, "error: less than %zu elements read from %s\n",
                numElements, filename);
        return 0;
    }

    fclose (content);

    return 1;
}

注意:请勿在代码中使用魔术数字硬编码字符串。如果需要常量,{{ 1}}。这使您的代码更易于阅读和维护

脚注:

1。。请勿替换或删除部分原始问题。这样一来,您所做更改之前的所有评论和答案都将变得无关紧要。而是通过在原始内容的底部添加修改来添加到您的问题。这样,所有评论和答案将继续有意义。 (我知道您是新手,所以这一次不讨人喜欢,但是请不要继续做下去)

答案 2 :(得分:0)

如下初始化data1

unsigned char data1[4000] = { 0 };