Skip to content

Instantly share code, notes, and snippets.

@ChronoMonochrome
Last active May 29, 2020 11:32
Show Gist options
  • Save ChronoMonochrome/3208755e43c9c6c9cfcc1fbb2f450895 to your computer and use it in GitHub Desktop.
Save ChronoMonochrome/3208755e43c9c6c9cfcc1fbb2f450895 to your computer and use it in GitHub Desktop.
/*
* 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