C 程序 - 从文件中读取整数并解码秘密消息
C Program - reading integers from a file and decoding secret message
嘿 :) 我的代码需要一些帮助,我认为这大部分是正确的,但我无法弄清楚哪里出错了。
#include <stdio.h>
#include <stdlib.h>
int num_count(FILE* ptr){
int count = 0;
int numHolder = 0;
while((fscanf(ptr, "%d", &numHolder)) == 1){
count++;
}
return count;
}
void load_nums(FILE* ptr, int *codedPtr, int ncount){
int number = 0;
ncount = ncount - 1;
for(int i = 0; i <= ncount; i++){
fscanf(ptr, "%d", &number);
printf("%d", number);
*(codedPtr + i) = number;
}
return;
}
void decode(int *codedPtr, int ncount, char *decodedPtr){
char temp;
ncount = ncount - 1;
for(int i = 0; i <= ncount; i++){
temp = ((*(codedPtr + i) + *(codedPtr + (ncount - i))) + '0');
*decodedPtr = temp;
decodedPtr++;
}
return;
}
int main(int argc, char *argv[]){
int *codedPtr;
char *decodedPtr;
FILE *fp;
if (argc == 2){
fp = fopen(argv[1], "r+");
}
if(argc <= 1){
printf("Invalid command line: cmd infile outfile\n");
}
int numCount = num_count(fp);
printf("%d", *codedPtr);
codedPtr = (int*)calloc(numCount, sizeof(int));
decodedPtr = (char*)calloc(numCount, sizeof(char));
load_nums(fp, codedPtr, numCount);
decode(codedPtr, numCount, decodedPtr);
printf("\n%s\n\n", decodedPtr);
fclose(fp);
return(0);
}
我添加了一些打印函数来排除故障,在 load_nums 函数期间,printf 函数连续打印 0,它没有从指向的文件中读取正确的整数值。
你们中的任何人都可以帮助特别是 load_nums 功能吗?谢谢大家,如果您需要任何额外信息,请告诉我。 “-6 -76 53 -34 32 79 142 55 177 78”是指向的文件中的内容。
你让事情变得比他们需要的复杂得多。您正在为 codedPtr
和 decodedPtr
动态分配存储空间,无需两次遍历文件(一次计算整数,一次在分配后读取)。您的 decode
比必要的复杂得多,并且存在逻辑错误。添加 '0'
(在这种情况下没有必要——尽管通常是将十进制 数字 转换为其 ASCII 字符值)
要解决 load_nums
,将 return 类型更改为 int *
并根据需要使用 realloc
在 load_nums
内分配 codedPtr
增加分配的内存块的大小。然后 return 指向已分配内存块的指针,其中包含您的 int
值。将 ncount
作为指针传递(例如 int *ncount
),以便您可以使用读取的整数数更新该地址处的值,以便调用函数返回计数(main()
这里).
以这种方式进行分配可将您的文件 I/O 减少为一次通过文件(文件 I/O 是最耗时的操作之一)此外,您完全不需要对于 num_count()
函数。
将这些部分放在一起,您可以:
/* read integers from fp, dynamically allocating storage as needed,
* return pointer to allocated block holding integers and make ncount
* available through update pointer value.
*/
int *load_nums (FILE* fp, int *ncount)
{
int *codedPtr, avail = 2; /* declare pointer & no. to track allocated ints */
*ncount = 0; /* zero the value at ncount */
/* allocate avail no. of int to codedPtr - validate EVERY allocation */
if (!(codedPtr = malloc (avail * sizeof *codedPtr))) {
perror ("malloc-codedPtr");
return NULL;
}
while (fscanf (fp, "%d", &codedPtr[*ncount]) == 1) { /* read each int */
if (++(*ncount) == avail) { /* check if realloc needed (count == avail) */
/* always realloc to a temporary pointer */
void *tmp = realloc (codedPtr, 2 * avail * sizeof *codedPtr);
if (!tmp) { /* validate that realloc succeeds */
perror ("realloc-codedPtr");
return codedPtr; /* original codedPtr vals available on failure */
}
codedPtr = tmp; /* assign new block of mem to codedPtr */
avail *= 2; /* update avail with no. of int allocated */
}
}
return codedPtr; /* return pointer to allocated block of memory */
}
您可以将 main()
中的函数调用为 codedPtr = load_nums (fp, &numCount)
。可以用if(...)
语句包裹起来判断分配和读取是成功还是失败:
int *codedPtr = NULL, numCount = 0;
...
if (!(codedPtr = load_nums (fp, &numCount))) /* read file/validate */
return 1;
(不需要从 main()
传递 codedPtr
。您可以通过检查 numCount > 0
进一步验证——留给您)
对于您的 decode
函数,只需设置 for
循环,使用两个循环变量从开始和结束向中间迭代。这大大简化了事情,例如
void decode (int *codedPtr, int ncount, char *decodedPtr)
{
/* loop from ends to middle adding values, + '0' NOT required */
for (int i = 0, j = ncount - i - 1; i < j; i++, j--)
decodedPtr[i] = codedPtr[i] + codedPtr[j];
}
(i
从第一个整数值开始,j
在最后一个整数值。不要使用 *(codePtr + i)
而是使用 codePtr[i]
—— 尽管等效,索引表示法更容易阅读)
在 main()
中,您可以选择打开作为程序的第一个参数提供的文件,或者如果没有提供参数则默认从 stdin
读取(许多 Linux 公用事业工作)。添加一个简单的 三进制 就足够了。无论您是读取输入还是分配内存(或使用代码继续正确运行所必需的任何函数),您都无法正确使用该函数,除非您 检查 return判断操作是成功还是失败。课程:验证,验证,验证...。
总而言之,你可以这样做:
#include <stdio.h>
#include <stdlib.h>
/* read integers from fp, dynamically allocating storage as needed,
* return pointer to allocated block holding integers and make ncount
* available through update pointer value.
*/
int *load_nums (FILE* fp, int *ncount)
{
int *codedPtr, avail = 2; /* declare pointer & no. to track allocated ints */
*ncount = 0; /* zero the value at ncount */
/* allocate avail no. of int to codedPtr - validate EVERY allocation */
if (!(codedPtr = malloc (avail * sizeof *codedPtr))) {
perror ("malloc-codedPtr");
return NULL;
}
while (fscanf (fp, "%d", &codedPtr[*ncount]) == 1) { /* read each int */
if (++(*ncount) == avail) { /* check if realloc needed (count == avail) */
/* always realloc to a temporary pointer */
void *tmp = realloc (codedPtr, 2 * avail * sizeof *codedPtr);
if (!tmp) { /* validate that realloc succeeds */
perror ("realloc-codedPtr");
return codedPtr; /* original codedPtr vals available on failure */
}
codedPtr = tmp; /* assign new block of mem to codedPtr */
avail *= 2; /* update avail with no. of int allocated */
}
}
return codedPtr; /* return pointer to allocated block of memory */
}
void decode (int *codedPtr, int ncount, char *decodedPtr)
{
/* loop from ends to middle adding values, + '0' NOT required */
for (int i = 0, j = ncount - i - 1; i < j; i++, j--)
decodedPtr[i] = codedPtr[i] + codedPtr[j];
}
int main(int argc, char *argv[]) {
int *codedPtr = NULL, numCount = 0;
char *decodedPtr = NULL;
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
if (!(codedPtr = load_nums (fp, &numCount))) /* read file/validate */
return 1;
if (fp != stdin) /* close file if not stdin */
fclose (fp);
if (!(decodedPtr = malloc (numCount + 1))) { /* allocate/validate */
perror ("malloc-decodedPtr"); /* don't forget room for '[=13=]' */
return 1;
}
decode (codedPtr, numCount, decodedPtr); /* decode the message */
decodedPtr[numCount] = 0; /* nul-terminate */
puts (decodedPtr); /* output decoded message */
free (codedPtr); /* don't forge to free what you allocate */
free (decodedPtr);
}
示例Use/Output
测试你的程序,你发现解码后的消息是"Hello"
,例如
$ echo "-6 -76 53 -34 32 79 142 55 177 78" | ./bin/codedptr
Hello
内存Use/Error检查
在您编写的任何动态分配内存的代码中,您对分配的任何内存块负有 2 责任:(1) 始终保留指向内存块的起始地址 因此,(2) 当不再需要它时可以释放。
您必须使用内存错误检查程序来确保您不会尝试访问内存或写入 beyond/outside 您分配的块的边界,尝试读取或基于未初始化的条件跳转值,最后,确认您释放了所有已分配的内存。
对于Linux valgrind
是正常的选择。每个平台都有类似的内存检查器。它们都很简单易用,只需运行你的程序就可以了。
$ echo "-6 -76 53 -34 32 79 142 55 177 78" | valgrind ./bin/codedptr
==32184== Memcheck, a memory error detector
==32184== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==32184== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==32184== Command: ./bin/codedptr
==32184==
Hello
==32184==
==32184== HEAP SUMMARY:
==32184== in use at exit: 0 bytes in 0 blocks
==32184== total heap usage: 7 allocs, 7 frees, 5,251 bytes allocated
==32184==
==32184== All heap blocks were freed -- no leaks are possible
==32184==
==32184== For counts of detected and suppressed errors, rerun with: -v
==32184== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认您已释放所有分配的内存并且没有内存错误。
检查一下,如果您还有其他问题,请告诉我。
嘿 :) 我的代码需要一些帮助,我认为这大部分是正确的,但我无法弄清楚哪里出错了。
#include <stdio.h>
#include <stdlib.h>
int num_count(FILE* ptr){
int count = 0;
int numHolder = 0;
while((fscanf(ptr, "%d", &numHolder)) == 1){
count++;
}
return count;
}
void load_nums(FILE* ptr, int *codedPtr, int ncount){
int number = 0;
ncount = ncount - 1;
for(int i = 0; i <= ncount; i++){
fscanf(ptr, "%d", &number);
printf("%d", number);
*(codedPtr + i) = number;
}
return;
}
void decode(int *codedPtr, int ncount, char *decodedPtr){
char temp;
ncount = ncount - 1;
for(int i = 0; i <= ncount; i++){
temp = ((*(codedPtr + i) + *(codedPtr + (ncount - i))) + '0');
*decodedPtr = temp;
decodedPtr++;
}
return;
}
int main(int argc, char *argv[]){
int *codedPtr;
char *decodedPtr;
FILE *fp;
if (argc == 2){
fp = fopen(argv[1], "r+");
}
if(argc <= 1){
printf("Invalid command line: cmd infile outfile\n");
}
int numCount = num_count(fp);
printf("%d", *codedPtr);
codedPtr = (int*)calloc(numCount, sizeof(int));
decodedPtr = (char*)calloc(numCount, sizeof(char));
load_nums(fp, codedPtr, numCount);
decode(codedPtr, numCount, decodedPtr);
printf("\n%s\n\n", decodedPtr);
fclose(fp);
return(0);
}
我添加了一些打印函数来排除故障,在 load_nums 函数期间,printf 函数连续打印 0,它没有从指向的文件中读取正确的整数值。
你们中的任何人都可以帮助特别是 load_nums 功能吗?谢谢大家,如果您需要任何额外信息,请告诉我。 “-6 -76 53 -34 32 79 142 55 177 78”是指向的文件中的内容。
你让事情变得比他们需要的复杂得多。您正在为 codedPtr
和 decodedPtr
动态分配存储空间,无需两次遍历文件(一次计算整数,一次在分配后读取)。您的 decode
比必要的复杂得多,并且存在逻辑错误。添加 '0'
(在这种情况下没有必要——尽管通常是将十进制 数字 转换为其 ASCII 字符值)
要解决 load_nums
,将 return 类型更改为 int *
并根据需要使用 realloc
在 load_nums
内分配 codedPtr
增加分配的内存块的大小。然后 return 指向已分配内存块的指针,其中包含您的 int
值。将 ncount
作为指针传递(例如 int *ncount
),以便您可以使用读取的整数数更新该地址处的值,以便调用函数返回计数(main()
这里).
以这种方式进行分配可将您的文件 I/O 减少为一次通过文件(文件 I/O 是最耗时的操作之一)此外,您完全不需要对于 num_count()
函数。
将这些部分放在一起,您可以:
/* read integers from fp, dynamically allocating storage as needed,
* return pointer to allocated block holding integers and make ncount
* available through update pointer value.
*/
int *load_nums (FILE* fp, int *ncount)
{
int *codedPtr, avail = 2; /* declare pointer & no. to track allocated ints */
*ncount = 0; /* zero the value at ncount */
/* allocate avail no. of int to codedPtr - validate EVERY allocation */
if (!(codedPtr = malloc (avail * sizeof *codedPtr))) {
perror ("malloc-codedPtr");
return NULL;
}
while (fscanf (fp, "%d", &codedPtr[*ncount]) == 1) { /* read each int */
if (++(*ncount) == avail) { /* check if realloc needed (count == avail) */
/* always realloc to a temporary pointer */
void *tmp = realloc (codedPtr, 2 * avail * sizeof *codedPtr);
if (!tmp) { /* validate that realloc succeeds */
perror ("realloc-codedPtr");
return codedPtr; /* original codedPtr vals available on failure */
}
codedPtr = tmp; /* assign new block of mem to codedPtr */
avail *= 2; /* update avail with no. of int allocated */
}
}
return codedPtr; /* return pointer to allocated block of memory */
}
您可以将 main()
中的函数调用为 codedPtr = load_nums (fp, &numCount)
。可以用if(...)
语句包裹起来判断分配和读取是成功还是失败:
int *codedPtr = NULL, numCount = 0;
...
if (!(codedPtr = load_nums (fp, &numCount))) /* read file/validate */
return 1;
(不需要从 main()
传递 codedPtr
。您可以通过检查 numCount > 0
进一步验证——留给您)
对于您的 decode
函数,只需设置 for
循环,使用两个循环变量从开始和结束向中间迭代。这大大简化了事情,例如
void decode (int *codedPtr, int ncount, char *decodedPtr)
{
/* loop from ends to middle adding values, + '0' NOT required */
for (int i = 0, j = ncount - i - 1; i < j; i++, j--)
decodedPtr[i] = codedPtr[i] + codedPtr[j];
}
(i
从第一个整数值开始,j
在最后一个整数值。不要使用 *(codePtr + i)
而是使用 codePtr[i]
—— 尽管等效,索引表示法更容易阅读)
在 main()
中,您可以选择打开作为程序的第一个参数提供的文件,或者如果没有提供参数则默认从 stdin
读取(许多 Linux 公用事业工作)。添加一个简单的 三进制 就足够了。无论您是读取输入还是分配内存(或使用代码继续正确运行所必需的任何函数),您都无法正确使用该函数,除非您 检查 return判断操作是成功还是失败。课程:验证,验证,验证...。
总而言之,你可以这样做:
#include <stdio.h>
#include <stdlib.h>
/* read integers from fp, dynamically allocating storage as needed,
* return pointer to allocated block holding integers and make ncount
* available through update pointer value.
*/
int *load_nums (FILE* fp, int *ncount)
{
int *codedPtr, avail = 2; /* declare pointer & no. to track allocated ints */
*ncount = 0; /* zero the value at ncount */
/* allocate avail no. of int to codedPtr - validate EVERY allocation */
if (!(codedPtr = malloc (avail * sizeof *codedPtr))) {
perror ("malloc-codedPtr");
return NULL;
}
while (fscanf (fp, "%d", &codedPtr[*ncount]) == 1) { /* read each int */
if (++(*ncount) == avail) { /* check if realloc needed (count == avail) */
/* always realloc to a temporary pointer */
void *tmp = realloc (codedPtr, 2 * avail * sizeof *codedPtr);
if (!tmp) { /* validate that realloc succeeds */
perror ("realloc-codedPtr");
return codedPtr; /* original codedPtr vals available on failure */
}
codedPtr = tmp; /* assign new block of mem to codedPtr */
avail *= 2; /* update avail with no. of int allocated */
}
}
return codedPtr; /* return pointer to allocated block of memory */
}
void decode (int *codedPtr, int ncount, char *decodedPtr)
{
/* loop from ends to middle adding values, + '0' NOT required */
for (int i = 0, j = ncount - i - 1; i < j; i++, j--)
decodedPtr[i] = codedPtr[i] + codedPtr[j];
}
int main(int argc, char *argv[]) {
int *codedPtr = NULL, numCount = 0;
char *decodedPtr = NULL;
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
if (!(codedPtr = load_nums (fp, &numCount))) /* read file/validate */
return 1;
if (fp != stdin) /* close file if not stdin */
fclose (fp);
if (!(decodedPtr = malloc (numCount + 1))) { /* allocate/validate */
perror ("malloc-decodedPtr"); /* don't forget room for '[=13=]' */
return 1;
}
decode (codedPtr, numCount, decodedPtr); /* decode the message */
decodedPtr[numCount] = 0; /* nul-terminate */
puts (decodedPtr); /* output decoded message */
free (codedPtr); /* don't forge to free what you allocate */
free (decodedPtr);
}
示例Use/Output
测试你的程序,你发现解码后的消息是"Hello"
,例如
$ echo "-6 -76 53 -34 32 79 142 55 177 78" | ./bin/codedptr
Hello
内存Use/Error检查
在您编写的任何动态分配内存的代码中,您对分配的任何内存块负有 2 责任:(1) 始终保留指向内存块的起始地址 因此,(2) 当不再需要它时可以释放。
您必须使用内存错误检查程序来确保您不会尝试访问内存或写入 beyond/outside 您分配的块的边界,尝试读取或基于未初始化的条件跳转值,最后,确认您释放了所有已分配的内存。
对于Linux valgrind
是正常的选择。每个平台都有类似的内存检查器。它们都很简单易用,只需运行你的程序就可以了。
$ echo "-6 -76 53 -34 32 79 142 55 177 78" | valgrind ./bin/codedptr
==32184== Memcheck, a memory error detector
==32184== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==32184== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==32184== Command: ./bin/codedptr
==32184==
Hello
==32184==
==32184== HEAP SUMMARY:
==32184== in use at exit: 0 bytes in 0 blocks
==32184== total heap usage: 7 allocs, 7 frees, 5,251 bytes allocated
==32184==
==32184== All heap blocks were freed -- no leaks are possible
==32184==
==32184== For counts of detected and suppressed errors, rerun with: -v
==32184== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认您已释放所有分配的内存并且没有内存错误。
检查一下,如果您还有其他问题,请告诉我。