[英]C Program executing differently from shell
I am trying to read this input as characters into memory in c in a 2 dimensional array.我正在尝试将此输入作为字符读取到二维数组中的 c 中的内存中。
00P015
00P116
030000
06P0ZZ
030005
06P1ZZ
04P0ZZ
26P1ZZ
3412ZZ
030010
06P0ZZ
99ZZZZ
030010
06P1ZZ
99ZZZZ
ZZ0000
ZZ0010
My code is我的代码是
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int pr;
int value;
/*These are variables representing the VM itself*/
char IR[6] ;
short int PC = 0 ;
int P0 ; //these are the pointer registers
int P1 ;
int P2 ;
int P3 ;
int R0 ; //GP regs
int R1 ;
int R2 ;
int R3 ;
int ACC ;
char PSW[2];
char memory [100][6] ; //this is the program memory for first program
short int opcode ; //nice to know what we are doing
int program_line = 0 ;
int fp ;
int i ;
int q = -1; //Used to iterate through memory to execute program
int TrueFalse; //True / False value for check statements, 1 implies true, 0 implies false
int halt = 0;
int address;
char input_line [7] ;
main(int argc, char *argv[])
{ //Read file into VM
fp = open("C:\\Users\\Whiskey Golf\\ClionProjects\\untitled\\program.txt", O_RDONLY) ;
printf("Open is %d\n", fp) ; //always check the return value.
if (fp < 0) //error in read
{printf("Could not open file\n");
exit(0) ;
}
//read in the first line of the program
int charRead = read (fp, input_line, 8 ) ; //returns number of characters read`
printf("\n*******************************\n");
printf("* Reading Program Into Memory *\n");
printf("*******************************\n");
while (1)
{ if (charRead <= 0) //indicates end of file or error
break ; //breaks out of infinite loop
for (i = 0; i < 6 ; i++) //If we get here must have correctly read in a line of program code.
memory[program_line][i] = input_line[i] ; //copy from input line into program memory
printf("Program Line %d: ", program_line) ; //printing out program line for debugging purposes
for(i = 0; i < 6; i++)
printf("%c", memory[program_line][i]) ;
printf("\n") ;
opcode = (memory[program_line][0] -48) *10 ; //Get opcode, print out opcode to console
opcode += (memory[program_line][1] -48) ;
printf("Opcode is %d\n", opcode) ;
charRead = read (fp, input_line, 8) ; //read in next line of code
if(input_line[0] == 'Z') //if the firat character is a 'Z' then you are reading data.
break ; //No more program code so break out of loop
program_line++ ; //now at a new line in the prog
printf("%n");
}
The issue I am having is that when I run the program in the IDE I wrote it in, Clion, my output is correct, I get我遇到的问题是,当我在我编写的 IDE 中运行程序时,Clion,我的输出是正确的,我得到
Program Line 0: 00P015
Opcode is 0
Program Line 1: 00P116
Opcode is 0
Program Line 2: 030000
Opcode is 3
Program Line 3: 06P0ZZ
Opcode is 6
But when I run the code via a shell via gcc compilation then ./a.out execution, the output I get is但是当我通过 gcc 编译通过 shell 运行代码然后 ./a.out 执行时,我得到的输出是
Program Line 0: 00P015
Opcode is 0
Program Line 1: 16
Opcode is -528
Program Line 2: 00
Opcode is -528
Program Line 3: ZZ
Opcode is-528
I have been trying to debug this issue for a while now, and I can not get it to work correctly when I do it through the shell, which is the way I need to do it.我已经尝试调试这个问题一段时间了,但是当我通过 shell 进行调试时,我无法让它正常工作,这是我需要的方式。 Any help would be greatly appreciated.
任何帮助将不胜感激。
You are reading 8
bytes which takes the end of line character '\\n'
and tries to store it in a 7
bytes array.您正在读取
8
个字节,它采用行尾字符'\\n'
并尝试将其存储在7
个字节的数组中。
read (fp, input_line, 8)
this leads to undefined behavrio, and it should be这会导致未定义的行为,应该是
read(fp, input_line, 7)
And then you could just discard the next byte like然后你可以丢弃下一个字节
char discard;
read(fp, &discard, 1);
I suppose you was reading 8
bytes to consume the end of line character, so you could have increased the array size to 8
and ignore the last character or simply read it and discard it.我想您正在读取
8
个字节来消耗行尾字符,因此您可以将数组大小增加到8
并忽略最后一个字符,或者只是读取它并丢弃它。
EDIT : Looking closely at the data and your code, I found out that I don't understand what you try to do, you must read just 7
characters, that will include the trailing '\\n'
, the following code will work if and only if there is always a new line '\\n'
after each line, otherwise it will skip the last line, you should think of the obvious solution yourself.编辑:仔细查看数据和您的代码,我发现我不明白您尝试做什么,您必须只读取
7
字符,其中将包括尾随'\\n'
,如果和,以下代码将起作用只有在每行后面总是有一个新行'\\n'
,否则会跳过最后一行,你应该自己考虑明显的解决方案。 Also, see this comment , if you write the program with a text editor on MS Windows, you will have trouble.另外,请参阅此评论,如果您在 MS Windows 上使用文本编辑器编写程序,则会遇到麻烦。 To solve that you can just use
fopen()
instead of low level I/O.要解决这个问题,您可以使用
fopen()
而不是低级 I/O。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int
main(void)
{
int file;
ssize_t length;
char buffer[7];
file = open("program.txt", O_RDONLY);
if (file == -1)
return -1;
while ((length = read(file, buffer, sizeof(buffer))) == 0)
{
int opcode;
/* You will need to overwrite the '\n' for the printf() to work
* but you can skip this if you don't want to print the command
*/
buffer[length - 1] = '\0';
opcode = 10 * (buffer[0] - '0') + buffer[1] - '0';
fprintf(stderr, "Command: `%s'\n\topcode: %d\n", buffer, opcode);
}
close(file);
return 0;
}
char input_line [7] ;
int charRead = read (fp, input_line, 8 ) ;
Reads 8 bytes into a 7 byte array, which is bad.将 8 个字节读入 7 个字节的数组,这是错误的。 It just wrote over some memory after the array, but since the array is 7 bytes and most data is aligned on 4 or 8 byte values, you probably get away with it by not reading data over anything important.
它只是在数组之后写入了一些内存,但是由于数组是 7 个字节,并且大多数数据都在 4 或 8 字节值上对齐,因此您可能不会通过读取任何重要的数据而逃脱它。
But!!!但!!! Here is your data:
这是您的数据:
00P015<EOL>
00P116<EOL>
030000<EOL>
06P0ZZ<EOL>
030005<EOL>
...
On a Unix-based system where the end of line is one byte, reading 8 bytes will read在行尾为 1 个字节的基于 Unix 的系统上,读取 8 个字节将读取
00P015<EOL>0
And the next eight bytes will read接下来的八个字节将读取
0P116<EOL>03
etcetera... So here is your data on drugs:等等......所以这是你的药物数据:
00P015<EOL>0
0P116<EOL>03
0000<EOL>06P
0ZZ<EOL>0300
05<EOL>...
See what happens?走着瞧吧? Not what you need or want.
不是您需要或想要的。
How this could work in the IDE, smurfed if I know, unless the input file is actually a windows text file (two byte end of line mark), but it's playing with fire.这如何在 IDE 中工作,如果我知道,除非输入文件实际上是一个 Windows 文本文件(行尾标记的两个字节),但它正在玩火。 I'm going to stick with C and pitch fscanf as an alternative to read.
我将坚持使用 C 并将fscanf作为阅读的替代方案。 I also stripped out all of the stuff not essential to this example.
我还去掉了所有对这个例子不重要的东西。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
(void) argc; // I'm being pedantic. As pointed out below in the comments, this
// is not needed. Main needs no arguments. I just like them.
(void) argv;
//Read file into VM
// moved all variables into function
char memory [100][6] ; //This is likely program death if you read more than 100
// lines from the file. There are no guards to prevent this
// in the original code.
int opcode ;
int program_line = 0 ;
FILE* fp ; //using a C FILE handle rather than a posix handle for maximum portability
char input_line [8] ;// death if a line is poorly formatted and has extra characters,
// but in this case, the whole program falls apart.
// Went with 8 in case the input file was formatted for Windows.
fp = fopen("asd.txt", "r") ; // using c standard library file open
if (fp == NULL)
{
printf("Could not open file\n");
return 0 ;
}
int itemsRead = fscanf(fp, "%s\n", input_line) ;
//fscanf is a much more tractable reader. This will read one string of characters
// up to the end of line. It will easily and happily run past the end of input_line
// if the line is poorly formatted
// handles a variety of EOL types. and returns the number of the requested
// items read. In this case, one item.
printf("\n*******************************\n");
printf("* Reading Program Into Memory *\n");
printf("*******************************\n");
while (itemsRead == 1 && input_line[0] != 'Z' && program_line < 100)
{ // much better place for the exit conditions. Also added test to prevent
// overrunning memory
for (int i = 0; i < 6 ; i++)
{
memory[program_line][i] = input_line[i] ;
} // this can also be performed with memcpy
printf("Program Line %d: ", program_line) ;
for(int i = 0; i < 6; i++)
{
printf("%c", memory[program_line][i]) ;
} // if we were using properly terminated c-style strings, and we are not,
// this loop and the following printf("\n") could be replaced with
// printf("%s\n", memory[program_line]). As it is putc would be a more
// efficient option
printf("\n") ;
opcode = (memory[program_line][0] -'0') *10 ; // '0' much easier to read than 48
opcode += memory[program_line][1] -'0' ;
printf("Opcode is %d\n", opcode) ;
charRead = fscanf(fp, "%s\n", input_line) ;
program_line++ ;
printf("\n"); // fixed typo
}
}
And in C++, this sucker is trivial而在 C++ 中,这个傻瓜是微不足道的
#include <iostream>
#include <fstream>
#include <vector>
int main(int argc, char *argv[])
{
(void) argc; // I'm still being pedantic.
(void) argv;
//Read file into VM
std::vector<std::string> memory;
int opcode;
std::ifstream in("asd.txt");
std::cout << "\n*******************************\n"
<< "* Reading Program Into Memory *\n"
<< "*******************************\n";
std::string input_line;
while (std::getline(in, input_line) && input_line[0] != 'Z')
{
memory.push_back(input_line);
std::cout << input_line << std::endl;
opcode = (input_line[0] - '0') * 10 + input_line[1] - '0';
std::cout << "Opcode is " << opcode << std::endl << std::endl;
}
}
A note on being pedantic.关于迂腐的注意事项。 There is this wonderful compiler option called
-pedantic
It instructs the compiler to do some fairly anally retentive error checking.有一个很棒的编译器选项,叫做
-pedantic
它指示编译器做一些相当保留的错误检查。 Add it , -Wall
, and -Wextra
to your command line.将它、
-Wall
和-Wextra
添加到您的命令行中。 Together they will spot a lot of mistakes.他们一起会发现很多错误。 And some stuff that isn't mistakes, but you can't win them all.
还有一些不是错误的东西,但你无法赢得它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.