Last active
May 29, 2020 11:32
-
-
Save ChronoMonochrome/3208755e43c9c6c9cfcc1fbb2f450895 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* File: myio.c | |
* YOUR NAME ... YOU NEED TO IMPLEMENT THE FUNCTIONS HERE.... | |
* | |
* .... | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include "myio.h" | |
/* | |
* Declarations of the private functions and structs | |
*/ | |
#define MINSIZE 100 | |
struct data { | |
char *buf; | |
int length; | |
}; | |
struct data myData; | |
struct MyInt { | |
int number; | |
int isNumber; | |
}; | |
struct MyInt myInt; | |
struct MyDouble { | |
double number; | |
int isNumber; | |
char integerPart[20]; | |
char floatingPart[20]; | |
}; | |
struct MyDouble myDouble; | |
struct data* myReadLine(FILE *infile); | |
struct MyInt *readInt(FILE *infile); | |
struct MyDouble *readDouble(FILE *infile); | |
/*--------------- END of declarations --------------------------*/ | |
#if 1 | |
void main(){ | |
double i = ReadDouble(); | |
printf("%f\n", i); | |
/* | |
struct MyInt *testInt = readInt(stdin); | |
if (testInt->isNumber) | |
printf("%d\n", testInt->number); | |
else | |
printf("%s", "entered invalid number"); | |
*/ | |
/*char *ptr = readline(stdin); | |
if (ptr) { | |
printf("%s", ptr); | |
free(ptr); | |
}*/ | |
} | |
#endif | |
/* | |
* Function: ReadInteger | |
* Usage: i = ReadInteger(); | |
* ------------------------ | |
* ReadInteger reads a line of text from standard input and scans | |
* it as an integer. To read the line, you can call the ReadLine() | |
* function that is described below. If all the characters in the | |
* given line are digits, then convert it to an integer and | |
* return it. The very first character could be the sign character | |
* '-' or '+'. | |
* Otherwise, if the given string contains any other character, | |
* this function will give an error meassage and keep asking user | |
* to enter a valid sequnece of characters that can be converted to | |
* an integer. | |
* The followings are valid integers: 234, -345, +453. | |
* The followings are not valid integers: 34 5, 3afg, 3-3, --45. | |
*/ | |
int ReadInteger(void) | |
{ | |
struct MyInt *testInt = readInt(stdin); | |
while (!testInt->isNumber) { | |
printf("%s", "Please enter a valid number\n"); | |
struct MyInt *testInt = readInt(stdin); | |
} | |
return testInt->number; | |
} | |
/* | |
* Function: readInt | |
* Usage: struct MyInt myInt = readInt(stdin); | |
* ------------------------ | |
* readInt is a helper function for ReadInteger(). Reads a line from the | |
* given file pointer, and tries to interprete the sequence of characters | |
* as an integer. Returns a struct containing the number (if any valid) | |
* number was input and the flag (isNumber) indicating whether the number is valid or not. | |
*/ | |
struct MyInt *readInt(FILE *infile) { | |
struct data *line = myReadLine(infile); | |
int res; | |
int isDigit = (line->buf[0] == '-' || line->buf[0] == '+' || (line->buf[0] >= '0' && line->buf[0] <= '9')); | |
int num = 0; | |
int i = line->length; | |
int order = 0; | |
int digit; | |
myInt.isNumber = isDigit; | |
if (!isDigit) { | |
free(line->buf); | |
return &myInt; | |
}; | |
while (i > -1) { | |
isDigit = (line->buf[i] >= '0' && line->buf[i] <= '9'); | |
if (i == 0 && (line->buf[0] == '-')) { | |
break; | |
} | |
if (i == 0 && (line->buf[0] == '+')) break; | |
if (!isDigit) { | |
free(line->buf); | |
myInt.isNumber = 0; | |
return &myInt; | |
}; | |
/* | |
* Convert the digit character to a number. | |
*/ | |
digit = (line->buf[i] - '0'); | |
for (int j = 0; j < order; j++) digit *= 10; | |
num += digit; | |
i--; | |
order+=1; | |
} | |
if (line->buf[0] != '-') | |
myInt.number = num; | |
else | |
myInt.number = -num; | |
myInt.isNumber = 1; | |
free(line->buf); | |
return &myInt; | |
} | |
/* | |
* Function: ReadDouble | |
* Usage: x = ReadDouble(); | |
* --------------------- | |
* ReadDouble reads a line of text from standard input and scans | |
* it as a double. As described above, you can call ReadLine() to | |
* read the line. If the number cannot be scanned as double or if | |
* extra characters follow after the number ends, this function | |
* gives an error and keep asking user to enter a valid double. | |
* The followings are valid doubless: 24, -35, +43, -23.54, +45.3 | |
* The followings are not valid doubles: 34 5, 3afg, 3.3.3, --45.5 | |
*/ | |
double ReadDouble(void) | |
{ | |
printf("%s", "Please enter a valid double\n"); | |
struct MyDouble *testDouble = readDouble(stdin); | |
while (!testDouble->isNumber) { | |
printf("%s", "Please enter a valid double\n"); | |
struct MyDouble *testDouble = readDouble(stdin); | |
} | |
return testDouble->number; | |
} | |
/* | |
* Function: readDouble | |
* Usage: struct MyDouble myDouble = readDouble(stdin); | |
* ------------------------ | |
* readDouble is a helper function for ReadDouble(). Reads a line from the | |
* given file pointer, and tries to interprete the sequence of characters | |
* as the double type. Returns a struct containing the number (if any valid | |
* number was input) and the flag (isNumber) indicating whether the number is valid or not. | |
*/ | |
struct MyDouble *readDouble(FILE *infile) { | |
struct data *line = myReadLine(infile); | |
int res; | |
int isDigit = (line->buf[0] == '-' || line->buf[0] == '+' || (line->buf[0] >= '0' && line->buf[0] <= '9')); | |
double num = 0; | |
int i = line->length; | |
int order = 0; | |
int digit; | |
int isIntegerPart = 1; | |
myDouble.isNumber = isDigit; | |
memset(&myDouble.integerPart, 0, 20); | |
memset(&myDouble.floatingPart, 0, 20); | |
if (!isDigit) { | |
free(line->buf); | |
return &myDouble; | |
}; | |
while (i > -1) { | |
i--; | |
if (line->buf[i] == '.') { | |
// if we already encountered '.', then not a valid number. | |
if (!isIntegerPart) { | |
myDouble.isNumber = 0; | |
return &myDouble; | |
} | |
// otherwise set corresponding flag to 0, for the later use | |
isIntegerPart = 0; | |
} | |
} | |
char *token = strtok(line->buf, "."); | |
snprintf(myDouble.integerPart, 20, "%s", token); | |
if (token) { | |
token = strtok(NULL, "."); | |
snprintf(myDouble.floatingPart, 20, "%s", token); | |
} | |
i = 0; | |
i = strlen(myDouble.integerPart) - 1; | |
while (i > -1) { | |
isDigit = (myDouble.integerPart[i] >= '0' && myDouble.integerPart[i] <= '9'); | |
if (i == 0 && (myDouble.integerPart[0] == '-')) { | |
break; | |
} | |
if (i == 0 && (myDouble.integerPart[0] == '+')) break; | |
if (!isDigit) { | |
free(line->buf); | |
myDouble.isNumber = 0; | |
return &myDouble; | |
}; | |
/* | |
* Convert the digit character to a number. | |
*/ | |
digit = (myDouble.integerPart[i] - '0'); | |
for (int j = 0; j < order; j++) digit *= 10; | |
num += digit; | |
//printf("%f", num); | |
i--; | |
order+=1; | |
} | |
double floatingPart; | |
double divisor = 1; | |
order = 0; | |
i = strlen(myDouble.floatingPart) - 1; | |
while (i > -1 && token) { | |
isDigit = (myDouble.floatingPart[i] >= '0' && myDouble.floatingPart[i] <= '9'); | |
if (i == 0 && (myDouble.floatingPart[0] == '-')) { | |
break; | |
} | |
if (i == 0 && (myDouble.floatingPart[0] == '+')) break; | |
if (!isDigit) { | |
free(line->buf); | |
myDouble.isNumber = 0; | |
return &myDouble; | |
}; | |
/* | |
* Convert the digit character to a number. | |
*/ | |
digit = (myDouble.floatingPart[i] - '0'); | |
for (int j = 0; j < order; j++) { | |
digit *= 10; | |
} | |
floatingPart += digit; | |
//printf("%f", num); | |
i--; | |
order+=1; | |
divisor *= 10.f; | |
} | |
//printf("floating part: %f\n", floatingPart); | |
num += (floatingPart / divisor); | |
if (line->buf[0] != '-') | |
myDouble.number = num; | |
else | |
myDouble.number = -num; | |
myDouble.isNumber = 1; | |
free(line->buf); | |
return &myDouble; | |
} | |
/* | |
// * Function: ReadLine | |
* Usage: s = ReadLine(); | |
* --------------------- | |
* ReadLine reads a line of text from standard input stdin and returns | |
* the line as a string. The newline character that terminates | |
* the input is not stored as part of the string. | |
* | |
* Note: this function above ReadLine(); can simply be implemented | |
* by using the next function as follows.. | |
* So, focus on the implementation of ReadLineFile(infile); below | |
*/ | |
char *ReadLine(void) | |
{ | |
return(ReadLineFile(stdin)); | |
} | |
/* | |
* Function: ReadLineFile | |
* Usage: s = ReadLineFile(infile); | |
* ---------------------------- | |
* ReadLineFile reads a line of text from the input file which | |
* is already open and pointed by infile. It then reads the line, | |
* dynamically allocates space, and returns the line as a string. | |
* The newline character that terminates the input is not stored | |
* as part of the string. | |
* The ReadLineFile function returns NULL if infile is at the | |
* end-of-file position. | |
*/ | |
char *ReadLineFile(FILE *infile) | |
{ | |
struct data *line = myReadLine(infile); | |
return line->buf; | |
} | |
/* | |
* Function: myReadLine | |
* Usage: struct data myData = myReadLine(stdin); | |
* ------------------------ | |
* myReadLine is a helper function for ReadLineFile(). | |
* In addition to ReadLineFile, it returns a struct, that contains | |
* the buffer, read from the file pointer infile and the length of this line. | |
*/ | |
struct data* myReadLine(FILE *infile) { | |
int bufSize = MINSIZE, i = 0; | |
int length; | |
char ch; | |
char *buf, *tmpbuf; | |
buf = calloc(bufSize, sizeof(char)); | |
while (1) { | |
ch = fgetc(infile); | |
if ((ch == EOF) || (ch == '\n')) { | |
buf[i] = 0; | |
length = i - 1; | |
break; | |
} | |
buf[i] = ch; | |
i++; | |
if (i >= bufSize) { | |
bufSize *= 2; | |
tmpbuf = realloc(buf, bufSize); | |
if (tmpbuf == NULL) { | |
printf("Memory not allocated.\n"); | |
free(buf); | |
return NULL; | |
} | |
buf = tmpbuf; | |
} | |
} | |
myData.buf = buf; | |
myData.length = length; | |
return &myData; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment