使用 sscanf 进行解析不会保留数组以供后续使用
Parsing using sscanf doesn't preserve arrays for subsequent use
我正在从事一个模拟 n 路关联缓存映射的项目。但是,当尝试在后续等式中使用 address[i] 数组时,问题就出现了。我想我不明白为什么数组没有被保留。任何帮助将不胜感激。我不是最擅长 C 编码的人。现在的问题是从文件中读取并将这些值扫描到数组中。我相信我能弄清楚的其他一切。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
/*global variables */
int mainSize, cacheSize, blockSize, cmSet, cnumBlocks, mnumBlocks,address[50],mmBlkNum[50], mappedCMset[50],hit_miss[50],address[50];
char mode[50];
int totMemRefs=0;
int main(void)
{
/*Variables */
int i;
char replacePolicy;
char filename[50];
char *result = NULL;
char line[50];
FILE *fp;
fp = fopen(filename, "r");
/*Gathers input from user */
printf("Enter the main memory size between between 4 and 32K bytes: ");
scanf("%d",&mainSize);
if (mainSize < 4 || mainSize > 32768)
{
printf("Invalid main memory size.");
//errorCheck()
}
printf("Enter the size of the cache between 2 and 32K bytes: ");
scanf("%d", &cacheSize);
if (cacheSize < 2 || cacheSize > 32768)
{
printf("Invalid cache memory size.");
//errorCheck()
}
printf("Enter the size of the block/line between 2 and 32K bytes: ");
scanf("%d",&blockSize);
if (blockSize < 2 || blockSize > 32768)
{
printf("Invalid block/line size.");
//errorCheck
}
printf("Enter the degree of set-associativity: ");
scanf("%d", &cmSet);
cnumBlocks = cacheSize/blockSize;
printf("Number of blocks in cache = %d\n", cnumBlocks);
mnumBlocks = mainSize/blockSize;
printf("Number of blocks in main memory = %d\n", mnumBlocks);
printf("Enter replacement policy (L = LRU, F = FIFO): ");
scanf("%s", &replacePolicy);
printf("Enter the name of the file containing the list of memory referenced: ");
scanf("%s", filename);
/* checks if filename is valid/exits */
if ((fp = fopen(filename, "r")) == NULL)
{
printf("Invalid input.");
//errorCheck();
}
/* gets total number of mem references from first line of file and stores in variable totMemRefs*/
fgets(line,sizeof(line),fp);
result = strtok(line,"\n");
totMemRefs = atoi(result);
printf("Total Mem Refs = %d\n", totMemRefs);
/*skips second line of white space */
fgets(line, sizeof(line),fp);
i=0;
//reads each line of file and tokenizes into mode and address
while (fgets(line, sizeof(line), fp)!=NULL)
{
if (sscanf(line,"%s %d",&mode[i],&address[i]) == 2)
{
printf("Mode: %c Address: %d\n",mode[i],address[i]);
i++;
}
}//end of parsing while loop
fclose(fp); //close file after reading
for (i=0; i<totMemRefs; i++)
{
/* calculates the corresponding block number of the address */
mmBlkNum[i]=address[i]/blockSize;
/* calculates the corresponding cache mem set that mm block is in */
mappedCMset[i]=mmBlkNum[i]%cnumBlocks;
printf("Mode = %c Address = %d MM Block Num = %d Cm Set = %d\n", mode[i],address[i],mmBlkNum[i],mappedCMset[i]);
}
}//end of main
这是example_test_data.txt的内容:
6
R 0
R 1
R 4
R 36
R 0
R 4
这些是主内存和高速缓存的特点:
main mem size = 128 bytes
cache mem size = 32 bytes
block size = 4 bytes
set associativity = 2
filename = example_test_data.txt
这是 while 循环中数组的输出:
Mode: R Address: 0
Mode: R Address: 1
Mode: R Address: 4
Mode: R Address: 36
Mode: R Address: 0
Mode: R Address: 4
这是解析后数组的输出 -- 在以下 for 循环中:
Mode = R Address = 4 MM Block Num = 1 Cm Set = 1
Mode = Address = 0 MM Block Num = 0 Cm Set = 0
Mode = Address = 0 MM Block Num = 0 Cm Set = 0
Mode = Address = 0 MM Block Num = 0 Cm Set = 0
Mode = Address = 0 MM Block Num = 0 Cm Set = 0
Mode = Address = 0 MM Block Num = 0 Cm Set = 0
如您所见,模式和地址数组的第二次迭代与文件 while 循环中的不同。我对为什么会这样感到困惑。我试图尽可能地描述。我也不知道为什么格式没有出现。对不起,如果这使它更难阅读。同样,我们将不胜感激任何朝着正确方向提供的帮助或推动!
编辑:
输出应该是:
Mode = R Address = 0 MM Blk Num = 0 CM Set = 0
Mode = R Address = 1 MM Blk Num = 0 CM Set = 0
Mode = R Address = 4 MM Blk Num = 1 CM Set = 1
Mode = R Address = 36 MM Blk Num = 9 CM Set = 1
Mode = R Address = 0 MM Blk Num = 0 CM Set = 0
Mode = R Address = 4 MM Blk Num = 1 CM Set = 1
我知道获得正确值所需的方程式。我知道如何手工处理这些没问题。所以知道结果应该是什么不是问题。
以前,我使用过 fscanf 和 strtok,但都没有产生预期的结果。基本上,当我在扫描时在 while 循环中打印它时,它会起作用,但是一旦我尝试计算 mmBlkNum 和 mappedCMset,数组中的值就不一样了。
代码已更新!!
我看到的第一个错误:
scanf("%s", &filename);
替换为正确的参数:
scanf("%s", filename);
请使用 -Wall
进行编译,这样编译器就会说出这些内容。结合 -Werror
。 -Wextra
也推荐。
我的编译器输出你的程序:
Whosebug.c: In function 'main':
Whosebug.c:246:11: error: format '%s' expects argument of type 'char *', but argument 2 has type 'char (*)[50]' [-Werror=format=]
scanf("%s", &filename);
^
cc1.exe: all warnings being treated as errors
我看到的第二个错误:您将阅读的所有内容放在 i = 0
循环中的同一索引处。使用 for
或正确使用 while
:
i = 0;
while (fgets(line, sizeof(line), fp)!=NULL && i < totMemRefs)
{
if (sscanf(line,"%s %d",&mode[i],&address[i]) == 2)
{
printf("Mode: %c Address: %d\n",mode[i],address[i]);
i++;
}
}//end of parsing while loop
if (i < totMemRefs)
{
fprintf(stderr, "Missing inputs.\n");
return 1;
}
我还添加了验证输入不超过用户说他将提供的输入数量,验证用户提供所有行。考虑在程序开头添加类似的内容:
#define MAX_INPUT_LINES 50
并使用 MAX_INPUT_LINES
而不是 50
。
我正在从事一个模拟 n 路关联缓存映射的项目。但是,当尝试在后续等式中使用 address[i] 数组时,问题就出现了。我想我不明白为什么数组没有被保留。任何帮助将不胜感激。我不是最擅长 C 编码的人。现在的问题是从文件中读取并将这些值扫描到数组中。我相信我能弄清楚的其他一切。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
/*global variables */
int mainSize, cacheSize, blockSize, cmSet, cnumBlocks, mnumBlocks,address[50],mmBlkNum[50], mappedCMset[50],hit_miss[50],address[50];
char mode[50];
int totMemRefs=0;
int main(void)
{
/*Variables */
int i;
char replacePolicy;
char filename[50];
char *result = NULL;
char line[50];
FILE *fp;
fp = fopen(filename, "r");
/*Gathers input from user */
printf("Enter the main memory size between between 4 and 32K bytes: ");
scanf("%d",&mainSize);
if (mainSize < 4 || mainSize > 32768)
{
printf("Invalid main memory size.");
//errorCheck()
}
printf("Enter the size of the cache between 2 and 32K bytes: ");
scanf("%d", &cacheSize);
if (cacheSize < 2 || cacheSize > 32768)
{
printf("Invalid cache memory size.");
//errorCheck()
}
printf("Enter the size of the block/line between 2 and 32K bytes: ");
scanf("%d",&blockSize);
if (blockSize < 2 || blockSize > 32768)
{
printf("Invalid block/line size.");
//errorCheck
}
printf("Enter the degree of set-associativity: ");
scanf("%d", &cmSet);
cnumBlocks = cacheSize/blockSize;
printf("Number of blocks in cache = %d\n", cnumBlocks);
mnumBlocks = mainSize/blockSize;
printf("Number of blocks in main memory = %d\n", mnumBlocks);
printf("Enter replacement policy (L = LRU, F = FIFO): ");
scanf("%s", &replacePolicy);
printf("Enter the name of the file containing the list of memory referenced: ");
scanf("%s", filename);
/* checks if filename is valid/exits */
if ((fp = fopen(filename, "r")) == NULL)
{
printf("Invalid input.");
//errorCheck();
}
/* gets total number of mem references from first line of file and stores in variable totMemRefs*/
fgets(line,sizeof(line),fp);
result = strtok(line,"\n");
totMemRefs = atoi(result);
printf("Total Mem Refs = %d\n", totMemRefs);
/*skips second line of white space */
fgets(line, sizeof(line),fp);
i=0;
//reads each line of file and tokenizes into mode and address
while (fgets(line, sizeof(line), fp)!=NULL)
{
if (sscanf(line,"%s %d",&mode[i],&address[i]) == 2)
{
printf("Mode: %c Address: %d\n",mode[i],address[i]);
i++;
}
}//end of parsing while loop
fclose(fp); //close file after reading
for (i=0; i<totMemRefs; i++)
{
/* calculates the corresponding block number of the address */
mmBlkNum[i]=address[i]/blockSize;
/* calculates the corresponding cache mem set that mm block is in */
mappedCMset[i]=mmBlkNum[i]%cnumBlocks;
printf("Mode = %c Address = %d MM Block Num = %d Cm Set = %d\n", mode[i],address[i],mmBlkNum[i],mappedCMset[i]);
}
}//end of main
这是example_test_data.txt的内容:
6
R 0
R 1
R 4
R 36
R 0
R 4
这些是主内存和高速缓存的特点:
main mem size = 128 bytes
cache mem size = 32 bytes
block size = 4 bytes
set associativity = 2
filename = example_test_data.txt
这是 while 循环中数组的输出:
Mode: R Address: 0
Mode: R Address: 1
Mode: R Address: 4
Mode: R Address: 36
Mode: R Address: 0
Mode: R Address: 4
这是解析后数组的输出 -- 在以下 for 循环中:
Mode = R Address = 4 MM Block Num = 1 Cm Set = 1
Mode = Address = 0 MM Block Num = 0 Cm Set = 0
Mode = Address = 0 MM Block Num = 0 Cm Set = 0
Mode = Address = 0 MM Block Num = 0 Cm Set = 0
Mode = Address = 0 MM Block Num = 0 Cm Set = 0
Mode = Address = 0 MM Block Num = 0 Cm Set = 0
如您所见,模式和地址数组的第二次迭代与文件 while 循环中的不同。我对为什么会这样感到困惑。我试图尽可能地描述。我也不知道为什么格式没有出现。对不起,如果这使它更难阅读。同样,我们将不胜感激任何朝着正确方向提供的帮助或推动!
编辑: 输出应该是:
Mode = R Address = 0 MM Blk Num = 0 CM Set = 0
Mode = R Address = 1 MM Blk Num = 0 CM Set = 0
Mode = R Address = 4 MM Blk Num = 1 CM Set = 1
Mode = R Address = 36 MM Blk Num = 9 CM Set = 1
Mode = R Address = 0 MM Blk Num = 0 CM Set = 0
Mode = R Address = 4 MM Blk Num = 1 CM Set = 1
我知道获得正确值所需的方程式。我知道如何手工处理这些没问题。所以知道结果应该是什么不是问题。 以前,我使用过 fscanf 和 strtok,但都没有产生预期的结果。基本上,当我在扫描时在 while 循环中打印它时,它会起作用,但是一旦我尝试计算 mmBlkNum 和 mappedCMset,数组中的值就不一样了。
代码已更新!!
我看到的第一个错误:
scanf("%s", &filename);
替换为正确的参数:
scanf("%s", filename);
请使用 -Wall
进行编译,这样编译器就会说出这些内容。结合 -Werror
。 -Wextra
也推荐。
我的编译器输出你的程序:
Whosebug.c: In function 'main':
Whosebug.c:246:11: error: format '%s' expects argument of type 'char *', but argument 2 has type 'char (*)[50]' [-Werror=format=]
scanf("%s", &filename);
^
cc1.exe: all warnings being treated as errors
我看到的第二个错误:您将阅读的所有内容放在 i = 0
循环中的同一索引处。使用 for
或正确使用 while
:
i = 0;
while (fgets(line, sizeof(line), fp)!=NULL && i < totMemRefs)
{
if (sscanf(line,"%s %d",&mode[i],&address[i]) == 2)
{
printf("Mode: %c Address: %d\n",mode[i],address[i]);
i++;
}
}//end of parsing while loop
if (i < totMemRefs)
{
fprintf(stderr, "Missing inputs.\n");
return 1;
}
我还添加了验证输入不超过用户说他将提供的输入数量,验证用户提供所有行。考虑在程序开头添加类似的内容:
#define MAX_INPUT_LINES 50
并使用 MAX_INPUT_LINES
而不是 50
。