Only printing last line of txt file when reading into struct array in C - c

I am reading from a txt file into an array of structures. Example txt:
-4.5 -1 0 0
4.0 1 0 0
8 0 1 2
12.1 0 -6 1
-3.2 2.5 -3.0 4
The 4 values of each line correspond to the 4 values in the structure. The file may contain up to 100 lines (MAX is defined as 100). With the following code I am trying to store each line into the respective index of the struct array and then print:
FILE *fileName = NULL;
typedef struct chargeData_struct {
double Q, x, y, z;
} ChargeData;
ChargeData values[MAX], *p = values;
fileName = fopen("charge2.txt", "r");
if (fileName == NULL)
{
printf("ERROR: Could not open file.");
}
int k = 0;
while (fscanf(fileName, "%lf %lf %lf %lf", &p[k].Q, &p[k].x, &p[k].y, &p[k].z) != EOF);
{
printf("%f %f %f %f\n", p[k].Q, p[k].x, p[k].y, p[k].z);
k++;
}
fclose(fileName);
However, only the last line of the txt file is printed. Is the same index of the struct array being overwritten each time?

You are using an extra semicolon which makes all the trouble, here:
while (fscanf(...) != EOF);
{
...
Remove it and you should be fine.
What happens with your code is that while(..); is equivalent to this:
while(...)
{
; // do nothing
}
thus does not enter the body (the one you think is the body) of your loop (since the actual body does nothing). However scanf() continues to parse the file, and then this section of your code executes:
{
printf("%f %f %f %f\n", p[k].Q, p[k].x, p[k].y, p[k].z);
k++;
}
independently, where the curly braces are treated like they wanted to state scope.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define LINE_BUFFER_LEN (512)
#define RESERVE_NEWLINDE 0
#define AUTO_FILTER_NEWLINDE 1
typedef int (* LINE_READER)(char * pstrLine, int uiBufferLen, void * pvData);
typedef struct st_HW_SSP_CONFIG
{
const char * pstrConfigPath;
LINE_READER pfLineReader;
FILE * pstFile;
void * pvData;
int CurrentLine;
int Flag;
} CONFIG_ST;
int CloseConfig(CONFIG_ST * pstConfig)
{
if (!pstConfig)
{
// record error
return -1;
}
if (fclose(pstConfig->pstFile))
{
// record error
}
return 0;
}
int OpenConfigFile(const char * pstrFilePath, CONFIG_ST * pstConfig)
{
FILE * pstFile = NULL;
if ((!pstrFilePath) || (!pstConfig))
{
return -1;
}
pstFile = fopen(pstrFilePath, "r");
if (!pstFile)
{
return -1;
}
pstConfig->pstFile = pstFile;
pstConfig->pstrConfigPath = pstrFilePath;
pstConfig->Flag = RESERVE_NEWLINDE;
return 0;
}
int IsNullStr(const char *pcStr)
{
const char *pcTmp = pcStr;
while ('\0' != *pcTmp)
{
if (!isspace(*pcTmp))
{
return 0;
}
pcTmp++;
}
return 1;
}
int IsEffectiveLine(char acFileLineBuffer[LINE_BUFFER_LEN])
{
if (0 == strlen(&acFileLineBuffer[0]))
{
return 0;
}
if ('#' == acFileLineBuffer[0]) // strip as a comment line
{
return 0;
}
if (IsNullStr(&acFileLineBuffer[0]))
{
return 0;
}
return 1;
}
void FilterNewLine(char* pcLine, int MaxNumLen)
{
int uiLen = strlen(pcLine);
if (uiLen > 1)
{
if ('\n' == pcLine[uiLen - 1])
{
pcLine[uiLen - 1] = '\0';
if (uiLen > 2)
{
if ('\r' == pcLine[uiLen - 2])
{
pcLine[uiLen - 2] = '\0';
}
}
}
}
return;
}
int ReadConfigFile(CONFIG_ST * pstConfig)
{
char acFileLineBuffer[LINE_BUFFER_LEN] = {0};
char * pstrRead = NULL;
int Ret = 0;
if (!pstConfig)
{
return -1;
}
if ((!pstConfig->pstFile) || (!pstConfig->pfLineReader))
{
return -1;
}
rewind(pstConfig->pstFile);
pstConfig->CurrentLine = 0;
do
{
memset((void *)&acFileLineBuffer[0], 0, LINE_BUFFER_LEN);
pstrRead = fgets(&acFileLineBuffer[0], LINE_BUFFER_LEN - 1, pstConfig->pstFile);
if (pstrRead)
{
pstConfig->CurrentLine ++;
if (0 == IsEffectiveLine(acFileLineBuffer))
{
continue;
}
if (AUTO_FILTER_NEWLINDE == pstConfig->Flag)
{
FilterNewLine(acFileLineBuffer, LINE_BUFFER_LEN - 1);
}
if (pstConfig->pfLineReader)
{
Ret = pstConfig->pfLineReader(&acFileLineBuffer[0],
LINE_BUFFER_LEN,
pstConfig->pvData);
if (Ret)
{
break;
}
}
}
}
while (pstrRead);
return Ret;
}
int ReadConfigFileEx(const char * pFilePath,
LINE_READER pfReader,
void * pData, int Flag)
{
int Ret = 0;
CONFIG_ST stConfig = {0};
Ret = OpenConfigFile(pFilePath, &stConfig);
if (Ret)
{
return Ret;
}
stConfig.pfLineReader = pfReader;
stConfig.pvData = pData;
stConfig.Flag = Flag;
Ret = ReadConfigFile(&stConfig);
CloseConfig(&stConfig);
return Ret;
}
int StringSplit(char *pcStr, char cFlag,
char * pstArray[], int MaxNum,
int *pNum)
{
char * pcStrTemp = 0;
unsigned int uiIndex = 0;
pcStrTemp = pcStr;
while (pcStrTemp)
{
pstArray[uiIndex] = pcStrTemp;
pcStrTemp = strchr(pcStrTemp, cFlag);
if (pcStrTemp)
{
*pcStrTemp = '\0';
pcStrTemp ++;
uiIndex ++;
}
if (uiIndex >= MaxNum)
{
break;
}
}
if (0 != MaxNum)
{
*pNum = uiIndex >= MaxNum ? (MaxNum - 1) : uiIndex;
}
else
{
*pNum = 0;
}
return 0;
}
int MyLineReader(char * pstrLine, int uiBufferLen, void * pvData)
{
printf("Read line:[%s]\r\n", pstrLine);
char *pArray[8] = {0};
int Num = 0;
int index = 0;
StringSplit(pstrLine, ' ', pArray, 8, &Num);
for (index = 0; index <= Num; index ++)
{
printf("Get value :[%s]\r\n", pArray[index]);
}
return 0;
}
int main(int argc, char * argv[])
{
int ret = 0;
if (argc != 2)
{
printf("Please input file to read.\r\n");
return 0;
}
ret = ReadConfigFileEx(argv[1], MyLineReader, NULL, AUTO_FILTER_NEWLINDE);
if (ret)
{
printf("Open file error.\r\n");
}
return 0;
}

Related

My problem with the size of the number in the My_Mastermind minigame

can you help me with the size of the digits, for example, when I enter 01234, then everything works as it should, but it shouldn’t, the limit of digits should be within four.When I enter some four-digit number, everything works as it should work. But when some five-digit, six-digit or even more, then everything works as if it should be, but it should not work like that. And when I enter numbers that are less than four-digit, for example 123 , then it gives an error and it's good. But when I enter numbers that are more than four digits, it does not give an error and works as if it should be so.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
typedef struct s_mastermind {
int my_attempt;
char* my_code;
} my_mastermind;
my_mastermind* settings_function(my_mastermind* mastermind, int argc, char** argv);
int checking_for_correctness_num(char* _string);
int wrong_input(int progress,char* num_code);
my_mastermind* my_function();
int check_function(char* string);
char* input_function();
int mis_placed_pieces(char* bit, char* num_code);
int well_placed_pieces(char* bit, char* num_code);
int code_checker(char* bit, char* num_code);
char* size_of_function(char* strye);
char* my_strcpy(char* num1, char* num2) {
for(int i = 0; num2[i] != 0; i++) {
num1[i] = num2[i];
}
return num1;
}
int my_strlen(char* num1) {
return (*num1) ? my_strlen(++num1) + 1 : 0;
}
my_mastermind* my_function() {
my_mastermind* num = malloc(sizeof(my_mastermind));
num->my_code = malloc(5);
num->my_code[4] = '\0';
my_strcpy(num->my_code, "");
num->my_attempt = 10;
return num;
}
my_mastermind* settings_function(my_mastermind* mastermind, int argc, char** argv) {
char* bit;
for(int i = 0; i < argc;) {
if (my_strlen(argv[i]) == 2 && argv[i][0] == '-') {
if(argv[i][1] == 'c') {
char* num_code = argv[i + 1];
if(wrong_input(argc,num_code) != 0) {
break;
}
my_strcpy(mastermind->my_code, num_code);
}else if(argv[i][1] == 't') {
if(checking_for_correctness_num(argv[i + 1]) == 0) {
mastermind->my_attempt = check_function(argv[i + 1]);
}
} else {
printf("WRONG FLAG RESTART THE GAME!!!\n");
}
}
i += 1;
}
return mastermind;
}
int wrong_input(int progress,char* num_code) {
// if(my_strlen(num_code) != 4) {
// printf("Code bigger than 4\n");
// }
if(checking_for_correctness_num(num_code) == 1) {
printf("Wrong input!\n> ");
fflush(stdout);
char* code = input_function();
char* variable = size_of_function(code);
free(code);
int results = 1;
if(wrong_input(progress,variable) == 0) {
results = code_checker(num_code, variable);
}
free(variable);
return results;
}
return 0;
}
int checking_for_correctness_num(char* _string) {
for(int i = 0; _string[i] != '\0'; i++) {
if(!(_string[i] >= '0' && _string[i] <= '9')) {
return 1;
}
}
return 0;
}
int check_function(char* string) {
int check_num = 0;
for(int i = 0; string[i] != '\0'; i++) {
check_num = check_num * 10 + (string[i] - '0');
}
return check_num;
}
char* input_function() {
char* getting = malloc(101);
getting[100] = '\0';
read(0, getting, 100);
fflush(stdout);
return getting;
}
int game_progress(int progress, char* bit) {
printf("Round: %d\n> ", progress);
fflush(stdout);
char* code = input_function();
char* variable = size_of_function(code);
free(code);
int results = 1;
if(wrong_input(progress,variable) == 0) {
results = code_checker(bit, variable);
}
free(variable);
return results;
}
void game_action(my_mastermind* mastermind) {
int current_try = 0;
for (;current_try < mastermind->my_attempt;) {
int results = game_progress(current_try, mastermind->my_code);
current_try += 1;
if(results == 0) {
printf("Congratz! You did it!\n");
break;
}
}
}
int code_checker(char* bit, char* num_code) {
int good_w = well_placed_pieces(bit, num_code);
int not_good_m = mis_placed_pieces(bit, num_code);
if(good_w == 3 || good_w == 2 || good_w == 1 || not_good_m == 3 || not_good_m == 2 || not_good_m == 1){
printf("Well placed pieces: %d\nMisplaced pieces: %d\n---\n", good_w,not_good_m);
}
if(good_w == 4) {
return 0;
} else {
return 1;
}
}
int well_placed_pieces(char* bit, char* num_code) {
int number = 0;
for(int i = 0; i < 4; i++) {
if (bit[i] == num_code[i]) {
number += 1;
}
}
return number;
}
int mis_placed_pieces(char* bit, char* num_code) {
int number = 0;
int i = 0;
int j = 0;
while(i < 4) {
i++;
if (bit[i] == num_code[i]) {
number += 1;
}
}
return number;
}
char* size_of_function(char* strye) {
char* new_string = malloc(5);
new_string[4] = '\0';
for(int i = 0; i < 4;i++){
new_string[i] = strye[i];
}
return new_string;
}
int main(int argc, char** argv) {
printf("Will you find the secret code?\n---\n");
my_mastermind* mastermind = my_function();
settings_function(mastermind, argc, argv);
game_action(mastermind);
free(mastermind);
return 0;
}
The problem is that you size_of_function assumes the input string is exactly 4 character long, not counting the '\0'. You should either check if the input string and return a error via a NULL pointer, or fully copy the string and check later.
Returning a NULL pointer require the least modification. You can do it by checking the input string size first :
char* size_of_function(char* strye) {
if(my_strlen(strye) != 4)
return NULL;
char* new_string = malloc(5);
new_string[4] = '\0';
for(int i = 0; i < 4;i++){
new_string[i] = strye[i];
}
if (strye[4] == '\r' || strye[4] == '\n' || strye[4] == '\0')
return new_string;
free(new_string);
return NULL;
}
Then, in wrong_input(), check if num_code is NULL :
int wrong_input(int progress,char* num_code) {
if(num_code == NULL || checking_for_correctness_num(num_code) == 1) {
printf("Wrong input!\n> ");
fflush(stdout);
char* code = input_function();
char* variable = size_of_function(code);
free(code);
int results = 1;
if(wrong_input(progress,variable) == 0) {
results = code_checker(num_code, variable);
}
free(variable);
return results;
}
return 0;
}
It is critical to check if num_code is NULL before calling checking_for_correctness_num(). In C the || operator evaluates the left operand first and skip the second operand evaluation if the first one is true. This way we can ensure that we never pass a NULL pointer to checking_for_correctness_num().
wrong_input() is called recursively and allocates memory without freeing it before calling itself. This can eat up memory fast and is generality considered to be bad practice.
Also, you've implemented my_strlen() as a recursive function, which isn't necessary. Using a loop is better :
int my_strlen(char* num1) {
int index = 0;
while(num1[index++]); //Note that 'index' is post-incremented
return index - 1; //Subtract one to account for the last post increment
}

Memory leak when changing size of read input

I´m facing really weird issue with my headtail application. When I try to read from file data.txt using Powershell (command: Get-Content data.txt | .\Headtail.exe head 10) I always get proper and expected output. However if I change input from data.txt to fail.txt I won´t get any output from output function (called vypis()).
Does anyone have an idead what is going on here?
GOOD CASE: Output from command (this output is suppose to be same using fail.txt as an input (meaning that content of the given input should be printed)) Get-Content data.txt | .\Headtail.exe head 10 in PowerShell:
aaaaaaaaaaaaaaaaaaaaaaaaaaaa.
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.
ccccccccccccccccccccc.
dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd.
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee.
ffffffffffffffffffffffffffffffffffffffffffffffffffff.
ggggggggggggggggggggggggggggggggg.
hhhhh.
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj.
WRONG CASE: Output from command Get-Content fail.txt | .\Headtail.exe head 10 in PowerShell:
/*NOTHING */
Code for my headtail function is following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
int const size = 15;
int last_changed = 0;
typedef struct {
char **field;
int *columns;
int rows;
} TMatrix;
void set_size(TMatrix* matrix) {
for (int i = 0; i < matrix->rows; i++) matrix->columns[i] = size;
}
TMatrix* allocate() {
TMatrix* matrix = malloc(sizeof(TMatrix));
if (!matrix) return NULL;
matrix->field = malloc(size * sizeof(char*));
if (!matrix->field) return NULL;
matrix->rows = size;
matrix->columns = malloc(size * sizeof(int));
if (!matrix->field) return NULL;
set_size(matrix);
for (int i = 0; i < matrix->rows; i++) {
matrix->field[i] = malloc(size * sizeof(char));
if (!matrix->field[i]) return NULL;
}
return matrix;
}
void release(TMatrix* matrix) {
for(int i = 0; i < matrix->rows; i++) free(matrix->field[i]);
free(matrix->field);
free(matrix->columns);
free(matrix);
}
bool add_rows(TMatrix* matrix) {
matrix->rows += 10;
char** rebuf = realloc(matrix->field, matrix->rows * sizeof(char*));
if (!rebuf) {
free(rebuf);
return false;
}
matrix->field = rebuf;
int* rebufl = realloc(matrix->columns, matrix->rows * sizeof(int));
if (!rebufl) {
free(rebufl);
return false;
}
matrix->columns = rebufl;
for (int i = 1; i <= 10; i++) {
char* rebuh = realloc(matrix->field[matrix->rows - i], size * sizeof(char));
if (!rebuh) {
free(rebuh);
return false;
}
matrix->field[matrix->rows - i] = rebuh;
matrix->columns[matrix->rows - i] = size;
}
return true;
}
bool add_column(TMatrix* matrix, int row) {
matrix->columns[row] += 15;
char* rebuf = realloc(matrix->field[row], matrix->columns[row] * sizeof(char));
if (!rebuf) {
free(rebuf);
return false;
}
matrix->field[row] = rebuf;
return true;
}
TMatrix* load(FILE* in) {
char c;
int actual_row = 0, actual_column = 0;
TMatrix* matrix;
if (!(matrix = allocate())) return NULL;
while ((fscanf(in, "%c", &c)) != EOF) {
matrix->field[actual_row][actual_column] = c;
if (c != '\n') {
actual_column += 1;
if (((matrix->columns[actual_row]) - 1) == actual_column) {
if (!add_column(matrix, actual_row)) return NULL;
}
}
else if (c == '\n') {
actual_column +=1;
if (((matrix->columns[actual_row]) - 1) == actual_column) {
if (!add_column(matrix, actual_row)) return NULL;
}
matrix->field[actual_row][actual_column] = '\0';
actual_column = 0;
actual_row += 1;
last_changed += 1;
if (((matrix->rows) - 1) == actual_row) {
if (!add_rows(matrix)) return NULL;
}
}
}
return matrix;
}
bool output(FILE* out, TMatrix *matrix, double num_of_output_lines, char method[]) {
if (!matrix) return false;
if (num_of_output_lines <= 0) return false;
if (matrix->rows <= 0) return false;
if (num_of_output_lines > last_changed) return false;
if (strcmp("head", method) == 0) {
for (int i = 0; i < num_of_output_lines; i++) {
for (int j = 0; j < matrix->columns[i]; j++) {
if (matrix->field[i][j] != '\0') fprintf(out, "%c", matrix->field[i][j]);
else break;
}
}
}
else if (strcmp("tail", method) == 0) {
for (int a = (last_changed-1); a >= (last_changed - num_of_output_lines); a--) {
for (int b = 0; b < matrix->columns[a]; b++) {
if (matrix->field[a][b] != '\0') fprintf(out, "%c", matrix->field[a][b]);
else break;
}
}
}
else return false;
return true;
}
void Help() {
fprintf(stdout, "-------------------------------------------------------------------------------------\n");
fprintf(stdout, "* Help function - nothing important *\n");
fprintf(stdout, "-------------------------------------------------------------------------------------\n");
}
int main(int argc, char *argv[])
{
if (argc < 3 || argc > 4) {
printf("!Valid count of arguments entered! \n");
return -1;
}
if (strcmp("-h", argv[1]) == 0) Help();
double num_of_output_lines = atoi(argv[argc - 1]);
TMatrix* matrix = load(stdin);
if (!matrix) {
printf("!Error while loading! \n");
return -1;
}
if (!output(stdout, matrix, num_of_output_lines, argv[argc - 2])) {
printf("!Error while printing! \n");
return -1;
}
release(matrix);
return 0;
}
And content of data.txt (works fine, just an example input):
aaaaaaaaaaaaaaaaaaaaaaaaaaaa.
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.
ccccccccccccccccccccc.
dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd.
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee.
ffffffffffffffffffffffffffffffffffffffffffffffffffff.
ggggggggggggggggggggggggggggggggg.
hhhhh.
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj.
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk.
lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll.
mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm.
nnnnnnnnnnnnnnnnnnnnnnnnn.
ooooooooooo.
ppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp.
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqq.
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr.
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss.
ttttttttttttttttttttt.
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu.
vvvvvvvvvvvvvvvvvvvvvvvvvvv.
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy.
zzzzzzzzzzzzzzzzzzzzzz.
And finally content of fail.txt (didn´t get any output, the difference is just in length of some rows):
aaaaa.
bbbbbbb.
cccc.
ddddddd.
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee.
ffffffffffffffffffffffffffffffffffffffffffffffffffff.
ggggggggggggggggggggggggggggggggg.
hhhhh.
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj.
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk.
lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll.
mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm.
nnnnnnnnnnnnnnnnnnnnnnnnn.
ooooooooooo.
ppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp.
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqq.
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr.
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss.
ttttttttttttttttttttt.
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu.
vvvvvvvvvvvvvvvvvvvvvvvvvvv.
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy.
zzzzzzzzzzzzzzzzzzzzzz.

reads txt from file, cut them into words, and display

#pragma warning(disable:4996)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
static WORDS heap[10000];
int heapSize;
void InitHeap()
{
heapSize = 0;
heap[0].words = NULL;
heap[0].count = -1;
}
void InsertHeap(char* string)
{
heapSize++;
strcpy(heap[heapSize].words, string);
int now = heapSize;
while (heap[now / 2].words > string)
{
heap[now] = heap[now / 2];
now /= 2;
}
strcpy(heap[now].words, string);
}
int DeleteHeap()
{
char* minElement, lastElement;
int child, now;
strcpy(minElement, heap[1].words);
strcpy(lastElement, heap[heapSize--].words);
for (now = 1; now * 2 <= heapSize; now = child)
{
child = now * 2;
if (child != heapSize && heap[child + 1].words < heap[child].words)
{
child++;
}
if (lastElement > heap[child].words)
{
strcpy(heap[now].words, heap[child].words);
}
else
{
break;
}
}
strcpy(heap[now].words, lastElement);
return now;
}
typedef struct _WORDS {
char words[64];
int count;
}WORDS;
char* MakeToken(void)
{
int i, j;
static char delim[256];
memset(delim, 0x0, 256);
for (i = 1, j = 0; i < 256; i++)
{
if (!isalpha(i)) delim[j++] = i;
}
return delim;
}
int main() {
int i = 0, cur = 0;
FILE *pFile;
char readLine[1024], *ptr;
char *token = MakeToken();
InitHeap();
pFile = fopen("C:\\Users\\Home\\Desktop\\dataset.txt", "r");
if (pFile == NULL) {
printf("File open failed.\n");
return 0;
}
while (fgets(readLine, 1024, pFile) != NULL) {
ptr = strtok(readLine, token);
while (ptr != NULL) {
InsertHeap(ptr);
ptr = strtok(NULL, token);
}
}
for (i = 0; i < heapSize; i++)
{
cur = DeleteHeap();
printf("%s %d\n", heap[cur].words, heap[cur].count);
}
return 0;
}
Error Message : Run-Time error #3
I want to make program that reads txt from file, cut them into words, and display on console. I make it, but it doesnt work. how to fix it?
I think static WORDS heap<- this part
or
delete part is error.
or its path is failure.
I see following errors in your code:
heap[0].words = NULL;
words is an array, not a dynamyc allocated pointer, so you cannot assign to NULL (you get a compiler error! Seems to me that the WORDS.word variable declaration is uncorrect).
strcpy(minElement, heap[1].words);
strcpy(lastElement, heap[heapSize--].words);
minElement and lastElement are not initialized and not allocated, so the strcpy function will fail.
Here is a way to correct the code, I changed the minimum possible. The following collect the words, count the number of occurences and print the result in alphabetical order:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct _WORDS {
char words[64];
int count;
} WORDS;
static WORDS heap[10000];
int heapSize;
void InitHeap()
{
heapSize = 0;
}
void InsertHeap(char* string)
{
int num = 0;
// Search string in heap array. if found, increase count.
for(num = 0; num < heapSize; ++num)
{
if(strcmp(string, heap[num].words) == 0)
{
heap[num].count++;
return;
}
}
// If not found, add it to the array.
strcpy(heap[heapSize].words, string);
heap[heapSize].count = 1;
heapSize++;
}
char* MakeToken(void)
{
int i, j;
static char delim[256];
memset(delim, 0x0, 256);
for (i = 1, j = 0; i < 256; i++)
{
if (!isalpha(i)) delim[j++] = i;
}
return delim;
}
int compare(const void* v1, const void* v2)
{
return strcmp((const char*)v1, (const char*)v2);
}
int main()
{
int i = 0, cur = 0;
FILE *pFile;
char readLine[1024], *ptr;
char *token = MakeToken();
InitHeap();
pFile = fopen("C:\\Users\\Home\\Desktop\\dataset.txt", "r");
if(pFile == NULL)
{
printf("File open failed.\n");
return 0;
}
while (fgets(readLine, 1024, pFile) != NULL)
{
ptr = strtok(readLine, token);
while (ptr != NULL)
{
InsertHeap(ptr);
ptr = strtok(NULL, token);
}
}
// Order alphabetically the heap array.
qsort(heap, heapSize, sizeof(WORDS), compare);
for (i = 0; i < heapSize; i++)
{
printf("%s %d\n", heap[i].words, heap[i].count);
}
return 0;
}
I've fixed some errors in the code and it started to produce some results. Since I do not understand completely your task, I cannot progress further. The working code is as follows:
#pragma warning(disable:4996)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct _WORDS { char words[64]; int count; }WORDS;
static WORDS app_heap[10000];
int heapSize;
void InitHeap()
{
heapSize = 0;
app_heap[0].words[0] = '\0';
app_heap[0].count = -1;
}
void InsertHeap(char* string)
{
heapSize++;
strcpy(app_heap[heapSize].words, string);
int now = heapSize;
while (app_heap[now / 2].words > string)
{
app_heap[now] = app_heap[now / 2];
now /= 2;
}
strcpy(app_heap[now].words, string);
}
int DeleteHeap()
{
char minElement[64], lastElement[64];
int child, now;
if(heapSize <= 0)
{
printf("Wrong call\n");
return 0;
}
strcpy(minElement, app_heap[1].words);
strcpy(lastElement, app_heap[heapSize--].words);
for (now = 1; now * 2 <= heapSize; now = child)
{
child = now * 2;
if (child != heapSize && app_heap[child + 1].words < app_heap[child].words)
{
child++;
}
if (lastElement > app_heap[child].words)
{
strcpy(app_heap[now].words, app_heap[child].words);
}
else
{
break;
}
}
strcpy(app_heap[now].words, lastElement);
return now;
}
char* MakeToken(void)
{
int i, j;
static char delim[256];
memset(delim, 0x0, 256);
for (i = 1, j = 0; i < 256; i++)
{
if (!isalpha(i)) delim[j++] = i;
}
return delim;
}
int main() {
int i = 0, cur = 0;
FILE *pFile;
char readLine[1024], *ptr;
char *token = MakeToken();
InitHeap();
pFile = fopen("dataset.txt", "r");
if (pFile == NULL) {
printf("File open failed.\n");
return 0;
}
while (fgets(readLine, 1024, pFile) != NULL) {
ptr = strtok(readLine, token);
while (ptr != NULL) {
InsertHeap(ptr);
ptr = strtok(NULL, token);
}
}
for (i = 0; i < heapSize; i++)
{
cur = DeleteHeap();
printf("%s %d\n", app_heap[cur].words, app_heap[cur].count);
}
return 0;
}

unexpected input value; log10 failed

When I write:
printf("%f; ", massive[i]);
Where:
double** InputSystemOfLinearEquationsByFile(FILE* file) {
char* inputc = (char*)malloc(quiteenoughelements * sizeof(char));
int thenumberofvaribles = 0;
int thenumberofequations = 0;
if (fscanf(file, "%s", inputc) == EOF) {
return NULL;
}
thenumberofvaribles = atoi(inputc);
if (thenumberofvaribles <= 0) {
return NULL;
}
if (fscanf(file, "%s", inputc) == EOF) {
return NULL;
}
thenumberofequations = atoi(inputc);
if (thenumberofequations <= 0) {
return NULL;
}
double** answer = (double**)malloc(thenumberofequations*sizeof(double*));
for (int i = 0; i < thenumberofequations; i++) {
answer[i] = (double*)malloc((thenumberofvaribles + 1)*sizeof(double));
}
for (int i = 0; i < thenumberofequations; i++) {
for (int j = 0; j < thenumberofvaribles; j++) {
if (fscanf(file, "%s", inputc) == EOF) {
return NULL;
}
answer[i][j] = atof(inputc);
}
}
for (int i = 0; i < thenumberofequations; i++) {
if (fscanf(file, "%s", inputc) == EOF) {
return NULL;
}
answer[i][thenumberofvaribles] = atof(inputc);
}
free(inputc);
return answer;
}
void SwapStrokes(double** matrix, const unsigned int stroke1index, const unsigned int stroke2index) {
double* temp = matrix[stroke1index];
matrix[stroke1index] = matrix[stroke2index];
matrix[stroke2index] = temp;
temp = NULL;
}
unsigned char ZeroCheck(double** matrix, const unsigned int currentstroke, const unsigned int currentcolumn, const unsigned int numberofequations) {
int numberofnotzerocolumn = currentstroke;
while ((fabs(matrix[numberofnotzerocolumn][currentcolumn]) < accuracy) || (matrix[numberofnotzerocolumn][currentcolumn] != matrix[numberofnotzerocolumn][currentcolumn])) {
numberofnotzerocolumn++;
if (numberofnotzerocolumn == numberofequations) {
return 1;
}
}
if (numberofnotzerocolumn != currentstroke) {
SwapStrokes(matrix, currentstroke, numberofnotzerocolumn);
}
return 0;
}
void JordanException(double** matrix, const unsigned int currentstroke, const unsigned int currentcolumn, const unsigned int numberofvars, const unsigned int numberofequations) {
int optionalcolumn = 0;
int optionalstroke = 0;
for (optionalstroke = 0; optionalstroke < currentstroke; optionalstroke++) {
for (optionalcolumn = 0; optionalcolumn < currentcolumn; optionalcolumn++) {
matrix[optionalstroke][optionalcolumn] -= matrix[optionalstroke][currentcolumn] * matrix[currentstroke][optionalcolumn] / matrix[currentstroke][currentcolumn];
}
optionalcolumn++;
for (optionalcolumn; optionalcolumn <= numberofvars; optionalcolumn++) {
matrix[optionalstroke][optionalcolumn] -= matrix[optionalstroke][currentcolumn] * matrix[currentstroke][optionalcolumn] / matrix[currentstroke][currentcolumn];
}
}
for (optionalstroke = currentstroke + 1; optionalstroke < numberofequations; optionalstroke++) {
for (optionalcolumn = 0; optionalcolumn < currentcolumn; optionalcolumn++) {
matrix[optionalstroke][optionalcolumn] -= matrix[optionalstroke][currentcolumn] * matrix[currentstroke][optionalcolumn] / matrix[currentstroke][currentcolumn];
}
optionalcolumn++;
for (optionalcolumn; optionalcolumn <= numberofvars; optionalcolumn++) {
matrix[optionalstroke][optionalcolumn] -= matrix[optionalstroke][currentcolumn] * matrix[currentstroke][optionalcolumn] / matrix[currentstroke][currentcolumn];
}
}
for (optionalcolumn = 0; optionalcolumn < currentcolumn; optionalcolumn++) {
matrix[currentstroke][optionalcolumn] /= matrix[currentstroke][currentcolumn];
}
optionalcolumn++;
for (optionalcolumn; optionalcolumn <= numberofvars; optionalcolumn++) {
matrix[currentstroke][optionalcolumn] /= matrix[currentstroke][currentcolumn];
}
for (optionalstroke = 0; optionalstroke < numberofequations; optionalstroke++) {
matrix[optionalstroke][currentcolumn] = 0.;
}
matrix[currentstroke][currentcolumn] = 1.;
}
double* JordanMethod(double** matrix, const unsigned int numberofvars, const unsigned int numberofequations) {
if (numberofvars > numberofequations) {
return NULL;
}
else {
unsigned int currentcolumn = 0;
unsigned int currentstroke = 0;
while ((currentcolumn < numberofvars) && (currentstroke < numberofequations)) {
if (ZeroCheck(matrix, currentstroke, currentcolumn, numberofequations) == 1) {
return NULL;
}
JordanException(matrix, currentstroke, currentcolumn, numberofvars, numberofequations);
currentstroke++;
currentcolumn++;
}
double* answer = (double*)malloc(numberofvars * sizeof(double));
for (currentstroke = 0; currentstroke < numberofvars; currentstroke++) {
if ((fabs(matrix[currentstroke][numberofvars]) < accuracy) || (matrix[currentstroke][numberofvars] != matrix[currentstroke][numberofvars])){
matrix[currentstroke][numberofvars] = 0.;
}
answer[currentstroke] = matrix[currentstroke][numberofvars];
}
return answer;
}
}
void WriteMassive(double* massive, unsigned int numberofelements, FILE* file) {
if ((massive != NULL) && (file != NULL)){
for (unsigned int i = 0; i < numberofelements; i++) {
fprintf(file, "%f; ", massive[i]);
}
fprintf(file, "\n");
}
}
int main(int argc, char **argv)
{
double* matrixa = NULL;
double** matrix = NULL;
FILE* file;
FILE* output;
file = fopen("File.txt", "r");
matrix = InputSystemOfLinearEquationsByFile(file);
matrixa = JordanMethod(matrix, 4, 4);
WriteMassive(matrixa, 4, output);
fclose(file);
system("pause");
return 0;
}
My file has got:
4
4
2 -1 5 7
3 3,5 4 -5
-7 -3 7,2 5,3
4 3 2,1 -3,5
I face this bug, when i=0:
> Debug Assertion Failed! Program: ...ConsoleApplication1.exe File:
> minkernel\crts\ucrt\src\appcrt\convert\cfout.cpp Line: 126 Expression:
> ("unexpected input value; log10 failed, 0)
What should I do?
P.s. While debugging I move cursed to massive[i] and visual studio show that it has normal value (something like 6.29...).
I've tried my code on VS 2013 (instead of 2015) and... It worked! Idk how it works, maybe it just problem with my computer.

Pointer to FILE nulling itself without being used at all

in the following code when ran will produce a Segmentation Fault, due to a FILE* being passed to fclose which contains no address (NULL).
I'm wondering why this is happening, the FILE* isn't being used what so over.
The FILE* is named urandom and is passed to fclose in the main function.
Thanks
#include <stdio.h>
#include <stdlib.h>
struct property
{
char *name;
unsigned int value;
unsigned int owner;
unsigned int type;
};
struct player
{
unsigned int id;
unsigned int money;
unsigned int position;
};
int rollDice(FILE *);
int amountOfLines(FILE *);
int createArrayOfPtrs(int ,void ***);
int makeArryOfPropertyPtrs(int ,struct property **);
int FillArryPropertyData(struct property **,int ,FILE *);
int splitBuffer(char *,unsigned int *,char **);
int bufferPropertyFile(FILE *,char **,int );
i nt fillPropertyStruct(struct property *,unsigned int ,char *);
int main(void)
{
int linesInPropertyFile = 0;
struct property **arrayForProperties = 0;
//Open /dev/urandom for rollDice
FILE *urandom = fopen("/dev/urandom","rb");
FILE *propertyFile = fopen("/home/jordan/Documents/Programming/Monopoly Project/properties","rb");
if(propertyFile == NULL || urandom == NULL)
{
puts("ERROR: error in opening file(s)");
return 1;
}
linesInPropertyFile = amountOfLines(propertyFile);
//DEBUG
printf("%d is contained within \"linesInPropertyFile\"\n",linesInPropertyFile);
if(createArrayOfPtrs(linesInPropertyFile,(void ***)&arrayForProperties))
{
puts("ERROR: error from createArrayOfPointers()");
return 1;
}
//DEBUG
printf("Outside Pointer: %p\n",arrayForProperties);
if(makeArryOfPropertyPtrs(linesInPropertyFile,arrayForProperties))
{
puts("ERROR: error from createArrayOfPointersForProperties()");
return 1;
}
if(FillArryPropertyData(arrayForProperties,linesInPropertyFile,propertyFile))
{
puts("ERROR: error from FillArryPropertyData()");
}
//Close FILE stream for /dev/urandom
fclose(urandom);
fclose(propertyFile);
return 0;
}
int FillArryPropertyData(struct property **array,int amntOfProperties,FILE *fp)
{
int bufferUsed = 100;
int i = 0;
int returnValue = 0;
int returnValue2 = 0;
unsigned int money = 0;
char *name;
char *buffer;
rewind(fp);
while(returnValue == 0)
{
buffer = malloc(bufferUsed);
returnValue = bufferPropertyFile(fp,&buffer,bufferUsed);
if(returnValue && returnValue != -1)
{
puts("ERROR: error from bufferPropertyFile()");
return -1;
}
if(returnValue == -1)
{
break;
}
if(buffer[0] != '\0')
{
returnValue2 = splitBuffer(buffer,&money,&name);
}
if(returnValue2)
{
puts("ERROR: error in splitBuffer()");
return 1;
}
if(fillPropertyStruct(array[i],money,name))
{
puts("ERROR: error in fillPropertyStruct()");
return 1;
}
money = 0;
i++;
}
free(buffer);
return 0;
}
int fillPropertyStruct(struct property *array,unsigned int money,char *name)
{
int nameSize = 100;
int i = 0;
array->name = malloc(nameSize);
array->value = money;
while(1)
{
if(i >= nameSize)
{
void *tmp = realloc(array->name,nameSize * 2);
nameSize *= 2;
if(tmp)
{
array->name = tmp;
}
else
{
return -1;
}
}
if(name[i] == '\0')
{
break;
}
array->name[i] = name[i];
i++;
}
array->name[i] = '\0';
return 0;
}
int splitBuffer(char *buffer,unsigned int *money,char **name)
{
int i = 0;
int j = 1;
int nameSize = 100;
*name = malloc(nameSize);
while(1)
{
if(buffer[j] != '"')
{
(*name)[j-1] = buffer[j];
}
else
{
i++;
}
j++;
if(i)
{
break;
}
if(j >= nameSize)
{
void *tmp = 0;
tmp = realloc(*name,nameSize * 2);
nameSize = nameSize * 2;
if(tmp != NULL)
{
*name = tmp;
}
else
{
puts("ERROR: error in splitBuffer");
return -1;
}
}
}
name[j-1] = '\0';
while(buffer[j] != '$')
{
if(buffer[j] == '\0')
{
puts("ERROR: error in splitBuffer()");
return -2;
}
j++;
}
j++;
while(buffer[j] != '\0')
{
*money += (buffer[j] - '0');
if(buffer[j+1] != '\0')
{
*money *= 10;
}
j++;
}
printf("BUFFER: %s\n",buffer);
printf("NAME: %s\n",*name);
printf("MONEY: %d\n",*money);
return 0;
}
int bufferPropertyFile(FILE *fp,char **buffer,int i)
{
int j = (i - i);
if(feof(fp))
{
//-1 Returned if EOF detected
return -1;
}
char retr = 0;
while(1)
{
if(j + 1 >= i)
{
void *tmp = realloc(*buffer,i * 2);
if(tmp != NULL)
{
*buffer = tmp;
i = i * 2;
}
else
{
puts("ERROR: error in bufferPropertyFile()");
return -2;
}
}
retr = fgetc(fp);
if(retr == '\n' || feof(fp))
{
break;
}
(*buffer)[j] = retr;
j++;
}
(*buffer)[j] = '\0';
if(**buffer == '\0')
{
return -1;
}
return 0;
}
int rollDice(FILE *fp)
{
int seed = fgetc(fp);
srand(seed);
return (rand() % 6) + 1;
}
int amountOfLines(FILE *file)
{
int i = 0;
int retr = 0;
while(1)
{
retr = fgetc(file);
if(retr == EOF)
{
break;
}
if(retr == '\n' )
{
i++;
}
}
return i;
}
int createArrayOfPtrs(int numberOfPointers,void ***pointer)
{
void *tmp = malloc(numberOfPointers * sizeof (tmp));
if(tmp != NULL)
{
*pointer = tmp;
//DEBUG
printf("Pointer: %p\n",*pointer);
}
else
{
return 1;
}
return 0;
}
int makeArryOfPropertyPtrs(int numberOfPointers,struct property **pointer)
{
int i = 0;
void *tmp;
for(i = 0;i < numberOfPointers;i++)
{
tmp = malloc(sizeof(struct property));
if(tmp == NULL)
{
return 1;
}
pointer[i] = (struct property *)tmp;
}
return 0;
}
here it givest an access violation in splitBuffer on this line:
name[j-1]='\0';
which probably should be
(*name)[j-1]='\0';
indeed that memory is not allocated anywhere, in other words, undefined behaviour, which indeed in your case might overwrite the urandom variable: both urandom and name are allocated on stack so depending on value of j it might write over urandom..
apart from that, there might be more errors, the number and use of pointers/mallocs/reallocs and lack of frees is a bit scary
int createArrayOfPtrs(int ,void ***);
if(createArrayOfPtrs(linesInPropertyFile,(void ***)&arrayForProperties))
This is undefined behaviour, a (void***) is not compatible to a (struct property ***). Why do you even use it here, all the other functions use struct property pointers?
Since the array is located right before the file pointer in the local variables of main, maybe the problem is that the array creation/initialization overwrites urandom?

Resources