C程序执行与shell

时间:2015-09-24 23:40:49

标签: c++ c

我正在尝试将此输入作为字符读入二维数组中的c中的内存中。

00P015
00P116
030000
06P0ZZ
030005
06P1ZZ
04P0ZZ
26P1ZZ
3412ZZ
030010
06P0ZZ
99ZZZZ
030010
06P1ZZ
99ZZZZ
ZZ0000
ZZ0010

我的代码是

#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");
    }

我遇到的问题是,当我在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

但是当我通过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

我一直试图调试这个问题一段时间了,当我通过shell执行它时,我无法让它正常工作,这是我需要这样做的方式。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

您正在读取8字节,该字节采用行尾字符'\n'并尝试将其存储在7字节数组中。

read (fp, input_line, 8)

这导致未定义的行为,它应该是

read(fp, input_line, 7)

然后你可以丢弃下一个字节,如

char discard; 
read(fp, &discard, 1);

我想您正在读取8字节以消耗行尾字符,因此您可以将数组大小增加到8并忽略最后一个字符或只是读取它并丢弃它。

编辑:仔细查看数据和代码,我发现我不明白你要做什么,你必须只阅读7个字符,其中包括尾随'\n',当且仅当在每行之后总是有新行'\n'时,以下代码才会起作用,否则它将跳过最后一行,你应该自己想到明显的解决方案。另外,请参阅this comment,如果您在MS Windows上使用文本编辑器编写程序,则会遇到问题。要解决此问题,您只需使用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;
}

答案 1 :(得分:1)

char input_line [7] ;

int charRead = read (fp, input_line, 8 ) ;

将8个字节读入7字节数组,这很糟糕。它只是在数组之后写了一些内存,但是因为数组是7个字节而且大多数数据是在4或8字节值上对齐的,所以你可能通过不读取任何重要的数据来逃避它。

但是!!!这是您的数据:

00P015<EOL>
00P116<EOL>
030000<EOL>
06P0ZZ<EOL>
030005<EOL>
...

在基于Unix的系统上,行尾是一个字节,读取8个字节将读取

00P015<EOL>0

接下来的八个字节将读取

0P116<EOL>03

etcetera ......所以这是你的毒品数据:

00P015<EOL>0
0P116<EOL>03
0000<EOL>06P
0ZZ<EOL>0300
05<EOL>...

看看会发生什么?不是你需要或想要的。

如果我知道,这可以在IDE中工作,除非输入文件实际上是一个Windows文本文件(行标记的两个字节末尾),但是它正在玩火。我会坚持使用C和fscanf作为阅读的替代方案。我还删除了所有对这个例子不重要的东西。

#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
    }
}

在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;
    }
}

关于迂腐的说明。有一个名为-pedantic的精彩编译器选项它指示编译器进行一些相当正常的保持性错误检查。将它-Wall-Wextra添加到命令行。他们将共同发现很多错误。还有一些不是错误的东西,但你无法全部赢得它们。