Reputation: 13
I'm writing the first pass of an assembler in C for an assignment and need to read in lines of a text file with assembly code, and store the label, opcode, and operand, as well as any comments in the line after the first three strings. I initially used
fscanf(fileptr1,"%s\t%s\t%s",label,opcode,operand);
for a file without comments, but sscanf wouldn't work to put the rest of the line into a single char array. It seems like I would use fgets
, but how would I separate that into the first three strings separated by whitespace, followed by the rest of the line until the newline character?
For reference, the lines follow this formatting:
LABEL OPCODE OPERAND COMMENTS IN MULTIPLE STRINGS
I would want the label, opcode, and operand in individual strings, as I have right now, and then a separate string for the entirety of the rest of the line. A few lines from the assembly code for reference:
COPY START 1000 COPY FILE FROM INPUT TO OUTPUT
FIRST STL RETADR SAVE RETURN ADDRESS
CLOOP JSUB RDREC READ INPUT RECORD
LDA LENGTH TEST FOR EOF (LENGTH = 0)
COMP ZERO
JEQ ENDFIL EXIT IF EOF FOUND
JSUB WRREC WRITE OUTPUT RECORD
J CLOOP LOOP
Upvotes: 1
Views: 192
Reputation: 93476
Define the specific delimiter for each field
fscanf( fileptr1, "%[^\t] %[^\t] %[^\t] %[^\n]", label, opcode, operand, comment ) ;
You should perhaps add field width specifiers and check the return value, to check for errors and overruns but that is a different question.
But there are other means. For example you could fgets()
the whole line into one array, then split it up using strtok()
using \t
as the delimiter.
char line[1024] = {0} ;
fgets( line, sizeof(line), fileptr1 ) ;
char* label = strtok( line, "\t" ) ;
char* opcode = label != 0 ? strtok( 0, "\t" ) : 0 ;
char* operand = opcode != 0 ? strtok( 0, "\t" ) : 0 ;
char* comment = operand != 0 ? strtok( 0, "\n" ) : 0 ;
Upvotes: 0
Reputation: 153517
Step 1: read the line with fgets()
char buffer[256];
while (fgets(buffer, sizeof buffer,fileptr1) {
how would I separate that into the first three strings separated by whitespace, ...
This is an incorrect assessment of the problem. The 3 "strings" are not separated by whitespace in the case of " LDA LENGTH TEST FOR EOF (LENGTH = 0)"
for the first "string" or label
is empty.
Instead code needs to look for missing fields.
Step 2: There are numerous approaches: Below is a try-it-1-of-2-ways depending on if leading character is a white-space. Test if scanning succeeded by testing n
char label[8];
char opcode[8];
char operand[12];
char comment[sizeof buffer]; // big enough to handle the rest of the line
label[0] = '\0';
opcode[0] = '\0';
operand[0] = '\0';
comment[0] = '\0';
int n = 0;
if (isspace((unsigned char) buffer[0])) {
// vv--------- Save offset of scan if we got that far
sscanf(buffer, "%7s%11s %n" , opcode, operand, &n);
} else {
sscanf(buffer, "%7s%7s%11s %n" , label, opcode, operand, &n);
}
if (n == 0) {
// Handle bad input with TBD code
continue;
}
// look for comment starting at `n`
if (buffer[n]) {
// scan in comment
sscanf(buffer + n, "%[^\n]" , comment);
}
// do something with input
printf("<%s> <%s> <%s> <%s>\n", label,opcode,operand,comment);
}
Code could test for a "too long" a label,opcode,operand
. Example:
// Assume max length of opcode == 7
char opcode[7 + 1 + 1]; // +1 for extra, +1 for null character
...
sscanf(..., "...%8s...", .... opcode ...);
if (opcode[7 + 1]) Handle_TooLoong();
Upvotes: 2