Read 2 files in C to calculate Manhattan Distance - c

I need some help just starting off my code for this program. This is my first time reading a file in c and I have been stuck starting it off. Essentially, I need to read in two files to calculate Manhattan Distance and output the ID for each file and the closest distance. The files look something like this:
3,2
0, 3.4, 4.3
1, 4.5, 6.1
2, 7.2, 3.9
3,2
0, 5.9, 6.7
1, 8.5, 1.2
2, 9.8, 4.9
My current code only outputs the table and I am trying to find a way to use columns as a way to calculate Manhattan distance. The 3,2 signifies the rows and columns and the 0,1,2 are the IDs. Here is the current code I have found online and modified a bit that I thought may be useful.
#include <stdio.h>
#include <string.h>
int main()
{
FILE* testFile = fopen("Test.txt", "r");
if (!testFile)
printf("Can't open file\n");
else {
char buffer[1024];
int row = 0;
int column = 0;
while (fgets(buffer, 1024, testFile)) {
column = 0;
row++;
if (row == 1)
continue;
// Splitting the data
char* value = strtok(buffer, ", ");
while (value) {
// Column 1
if (column == 0) {
printf("TestID:");
}
// Column 2
if (column == 1) {
printf("\tx1: ");
}
// Column 3
if (column == 2) {
printf("\ty1: ");
}
printf("%s", value);
value = strtok(NULL, ", ");
column++;
}
printf("\n");
}
// Close the file
fclose(testFile);
}
return 0;
}

Here's a basic example demonstrating one method of parsing your input files with strtod and strtoul:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct mat {
int rows;
int columns;
double *data;
};
void
show(const struct mat *A)
{
double *d = A->data;
for( int i = 0; i < A->rows; i += 1 ){
for( int j = 0; j < A->columns; j += 1 ){
printf("%f\t", *d++);
}
putchar('\n');
}
}
/*
* Return nonzero if the first non-whitespace
* character after *e is not v. Terminate search
* at a newline.
*/
int
expect_next(char **e, const char v)
{
char *end = *e;
while( isspace(*end) && *end != '\n' ){
end += 1;
}
*e = end + 1;
return *end != v;
}
int
get_data(struct mat *A, const char *path)
{
unsigned line = 1;
FILE* testFile = fopen(path, "r");
if( testFile == NULL ){
perror(path);
return 0;
}
char buffer[1024];
char *end = buffer;
if( fgets(buffer, sizeof buffer, testFile) == NULL ){
if( ferror(testFile) ){
perror(path);
} else {
goto bad_input;
}
return 0;
}
A->rows = strtoul(buffer, &end, 10);
if( expect_next(&end, ',') ){
goto bad_input;
}
A->columns = strtoul(end, &end, 10);
if( expect_next(&end, '\n') ){
goto bad_input;
}
A->data = malloc(A->rows * A->columns * sizeof *A->data);
if( A->data == NULL ){
perror("malloc");
return 0;
}
double *val = A->data;
unsigned row = 0;
while( NULL != fgets(buffer, sizeof buffer, testFile) ){
line += 1;
unsigned v = strtoul(buffer, &end, 10);
if( v != row ){
goto bad_input;
}
if( expect_next(&end, ',') ){
goto bad_input;
}
unsigned col = 0;
while( col < A->columns && *end ){
*val++ = strtod(end, &end);
if( expect_next(&end, ++col == A->columns ? '\n' : ',') ){
goto bad_input;
}
}
if( col != A->columns ){
goto bad_input;
}
row += 1;
}
if( row != A->rows ){
goto bad_input;
}
if( fclose(testFile) ){
perror(path);
}
return 1;
bad_input:
fprintf(stderr, "%s: Invalid input at line %u, column %u\n", path,
line, (unsigned)(end - buffer));
return 0;
}
int
main(int argc, char ** argv)
{
char *args[] = { NULL, "/dev/stdin", NULL };
if( argc < 2 ){
argv = args;
}
for( argv += 1; *argv; argv += 1 ){
struct mat A;
if( get_data(&A, *argv) ){
show(&A);
}
}
}

Related

One file to another file conversion in C

I have an input file named as datafile.data, which looks something like below:
1,2,1,1,0
1,3,1,1,0
1,1,2,2,1
2,1,2,2,1
2,3,2,3,1
1,1,2,3,2
3,1,1,4,2
2,1,3,2,2
3,3,3,1,2
2,2,3,4,2
Here the 1st 4 columns stands for 4 attribute values say A1, A2, A3, A4. And the final column stands for the class value. For this particular sample file there are 4 attributes but for some other files, there can be 'n' number of attributes but for every file, the last column will give the class values.
Now I want to convert this file to another file named as : outputfile.exp
Where the output file's 1st row looks something like below:
<Number of rows in the .data file> <Number of attributes> <Max value of A1> <Max value of A2> <Max value of A3> <Max value of A4> <(Max value of last column)+1>
And the remaining rows of the output file will be same as the data file, with just one change, that is the last column's each value will be incremented by 1.
For an example the output file for the above example will look like:
10 4 3 3 3 4 3
1,2,1,1,1
1,3,1,1,1
1,1,2,2,2
2,1,2,2,2
2,3,2,3,2
1,1,2,3,3
3,1,1,4,3
2,1,3,2,3
3,3,3,1,3
2,2,3,4,3
Where the 1st row's 10 is the number of rows, 4 is the number of attributes present, (3,3,3,4) these 4 are the maximum values of attributes A1,A2,A3 and A4 and last 3 stands for the highest class value +1. And the last column's every value has been incremented by 1 as well.
Below I am attaching my try:
#include <stdio.h>
#include <string.h>
#define MAX_FILE_NAME 100
int main()
{
FILE *fp;
int count = 0; // Line counter (result)
char filename[MAX_FILE_NAME], dataToBeRead[50];
char c; // To store a character read from file
// Open the file
fp = fopen("datafile.data", "r");
// Check if file exists
if (fp == NULL)
{
printf("Could not open file %s", filename);
return 0;
}
// Extract characters from file and store in character c
for (c = getc(fp); c != EOF; c = getc(fp))
if (c == '\n') // Increment count if this character is newline
count = count + 1;
fclose(fp);
printf("%d\n",count);
fp = fopen("datafile.data", "r");
if ( fp == NULL )
{
printf( "Failed to open." ) ;
}
else
{
while( fgets ( dataToBeRead, 50, fp ) != NULL )
{
printf( "%s" , dataToBeRead ) ;
}
fclose(fp) ;
}
return 0;
}
And I am getting the below output:
10
1,2,1,1,1
1,3,1,1,1
1,1,2,2,2
2,1,2,2,2
2,3,2,3,2
1,1,2,3,3
3,1,1,4,3
2,1,3,2,3
3,3,3,1,3
2,2,3,4,3
Now I am unable to proceed further, as I am very new to C, please help me out.
Edit 1 : The output format of the example will be:
10 4 3 3 3 4 3
1 2 1 1 1
1 3 1 1 1
1 1 2 2 2
2 1 2 2 2
2 3 2 3 2
1 1 2 3 3
3 1 1 4 3
2 1 3 2 3
3 3 3 1 3
2 2 3 4 3
You really don't want to do this, since rewinding an input stream is an anti-pattern. But you can do something like:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE * xfopen(const char *path, const char *mode);
void * xmalloc(size_t s);
void
parse_line(const char *buf, int *max, int column_count)
{
for(int i = 0; i < column_count; i++ ){
char *end;
int t = strtol(buf, &end, 10);
if( t > max[i] ){
max[i] = t;
}
if( !((i < column_count - 1 && *end == ',')
|| (i == column_count - 1 && *end == '\n'))
){
fprintf(stderr, "invalid input '%c' in %s", *end, buf);
exit(1);
}
buf = end + 1;
}
}
int
main(int argc, char **argv)
{
const char *path = argc > 1 ? argv[1] : "stdin";
FILE *in = argc > 1 ? xfopen(path, "r") : stdin;
char buf[1024];
int column_count = 1;
int row_count = 1;
int *max;
/* Read first line to determine number of columns */
if( fgets(buf, sizeof buf, in) == NULL ){
fputs("Input error\n", stderr);
return 1;
}
for( const char *p = buf; *p; p++ ){
if( *p == ',' ){
column_count += 1;
}
}
max = xmalloc(column_count * sizeof *max);
for( int i = 0; i < column_count; i++ ){
max[i] = INT_MIN;
}
parse_line(buf, max, column_count);
while( fgets(buf, sizeof buf, in) != NULL ){
row_count += 1;
parse_line(buf, max, column_count);
}
if( fseek(in, 0L, SEEK_SET) ){
perror(path);
return 1;
}
printf("%d %d ", row_count, column_count - 1);
for( int i = 0; i < column_count - 1; i += 1 ){
printf("%d ", max[i]);
}
printf("%d\n", max[column_count - 1] + 1);
while( fgets(buf, sizeof buf, in) != NULL ){
char *comma = strrchr(buf, ',');
if( comma == NULL ){
fprintf(stderr, "Invalid input\n");
return 1;
}
*comma = '\0';
int k = strtol(comma + 1, NULL, 10);
printf("%s,%d\n", buf, k + 1);
}
}
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
*mode == 'r' ? stdin : stdout;
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
void *
xmalloc(size_t s)
{
void *rv = malloc(s);
if( rv == NULL ){
perror("malloc");
exit(EXIT_FAILURE);
}
return rv;
}
You can execute this as ./a.out < datafile.data > outputfile.exp or ./a.out datafile.data > outputfile.exp, but this will not work if you try to read from a pipe (the seek will fail). The seek failure and the inability to run this as a filter make this a suboptimal approach, but storing the entire file in memory also has drawbacks.
As William Pursell has provided superb answer in C, here is an awk alternative, although awk is not tagged.
awk -F, -v OFS="," ' # assign input/output field separator to a comma
NR==FNR { # this block is invoked for the 1st read of the input file
for (i = 1; i <= NF; i++) { # loop over the filelds
if (max[i] == "" || max[i] < $i) max[i] = $i
# update the max values
}
nr = NR; nf = NF # store #records and #fields
next # skip following statements
}
FNR==1 { # this block is invoked just before reading he 1st line for the 2nd read of the input file
printf("%d %d ", nr, nf - 1) # print #records and #fields - 1
max[nf]++ # increment the max value of the last field
for (i = 1; i <= nf; i++) { # print max values
printf("%d%s", max[i], i==nf ? "\n" : " ");
}
}
{ # this block is invoked for the 2nd read
$nf++ # increment the value of the last field
print # print fields as csv
}
' datafile.data datafile.data # read the input file twice
Below is the modified code, where I want to read .names file first and then check whether the last line of that .names has a zero then I want to produce the output.
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE * xfopen(const char *path, const char *mode);
void * xmalloc(size_t s);
void parse_line(const char *buf, int *max, int column_count)
{
for(int i = 0; i < column_count; i++ ){
char *end;
int t = strtol(buf, &end, 10);
if( t > max[i] ){
max[i] = t;
}
if( !((i < column_count - 1 && *end == ',') || (i == column_count - 1 && *end == '\n')) ){
fprintf(stderr, "invalid input '%c' in %s", *end, buf);
exit(1);
}
buf = end + 1;
}
}
int main(int argc, char **argv)
{
char *path1;
char *path = argc > 1 ? argv[1] : "stdin";
sprintf(path, "%s.data", argv[1]);
FILE *in = argc > 1 ? xfopen(path, "r") : stdin;
char buf[1024];
int column_count = 1;
int row_count = 1;
int *max;
/* Read first line to determine number of columns */
if( fgets(buf, sizeof buf, in) == NULL ){
fputs("Input error\n", stderr);
return 1;
}
for( const char *p = buf; *p; p++ ){
if( *p == ',' ){
column_count += 1;
}
}
max = xmalloc(column_count * sizeof *max);
for( int i = 0; i < column_count; i++ ){
max[i] = INT_MIN;
}
parse_line(buf, max, column_count);
while( fgets(buf, sizeof buf, in) != NULL ){
row_count += 1;
parse_line(buf, max, column_count);
}
if( fseek(in, 0L, SEEK_SET) ){
perror(path);
return 1;
}
printf("%d %d ", row_count, column_count - 1);
for( int i = 0; i < column_count - 1; i += 1 ){
printf("%d ", max[i]);
}
printf("%d\n", max[column_count - 1] + 1);
while( fgets(buf, sizeof buf, in) != NULL ){
char *comma = strrchr(buf, ',');
if( comma == NULL ){
fprintf(stderr, "Invalid input\n");
return 1;
}
*comma = '\0';
int k = strtol(comma + 1, NULL, 10);
for(char *p = buf; *p; p++){
if( *p == ',' ) *p = ' ';
}
printf("%s %d\n", buf, k + 1);
}
}
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
*mode == 'r' ? stdin : stdout;
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
void *
xmalloc(size_t s)
{
void *rv = malloc(s);
if( rv == NULL ){
perror("malloc");
exit(EXIT_FAILURE);
}
return rv;
}

How to fill array with elements in a .txt file

I have a dynamic 2D float array and a file with both strings, integers(number of floats in the line) and float numbers.
M = (float**)malloc(num_lines * sizeof(float));
for(int i = 0; i < num_lines; i++){
M[i] = (float*)malloc(num_columns * sizeof(float));
}
Example:
2
John 3 5.5 89.5 30.67 0.00
Mary 4 78.9 67.4 67.3 9.0 0.00
(null)
The number of lines is the one on the file + 1 and the number of columns is the highest integer + 1 (5 in this case) because the 0.00 marks the end of each line.
How do I load only the floats into memory? I've tried different types of loops with fgets and strtok but it doesn't work due to the different types of variables.
The code is like this:
for(int i = 0; i < num_lines; i++){
fgets(buf, 1000, aux);
name = strtok(buf, " ");
col = atoi(strtok(NULL, " "));
for(j = 0; j < num_columns; j++){
M[i][j] = atof(strtok(NULL, " "));
if(M[i][j] == 0.00){
break;
}
}
}
This sort of parsing is a bit of a pain, but is a good exercise to do every now and again. This is relatively easy with scanf, but scanf is not suitable for anything but toys. (It is literally impossible to correctly handle anything robustly, since even a simple "%d" format specifier leads to undefined behavior on certain input.) Unless you are willing to read the file twice to determine the maximum size of a column, you can't preallocate the entire array. Instead of that, I would suggest doing something like:
#include <ctype.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* sample input
2
John 3 5.5 89.5 30.67 0.00
Mary 4 78.9 67.4 67.3 9.0 0.00
*/
FILE * xfopen(const char *, const char *);
void * xmalloc(size_t);
int get_row_count(FILE *in, char **line, size_t *cap, const char *name);
float * parse_line(const char *s, int lc);
int
main(int argc, char **argv)
{
int lc = 0;
char *line = NULL;
size_t cap = 0;
FILE *in = argc > 1 ? xfopen(argv[1], "r") : stdin;
int rows = get_row_count(in, &line, &cap, argv[1]);
float **M = xmalloc(rows * sizeof *M);
for( lc = 0; lc < rows && getline(&line, &cap, in) > 0; lc += 1 ){
M[lc] = parse_line(line, lc + 1);
}
if( lc != rows ){
warnx("invalid input: missing some rows");
}
for( int i = 0; i < lc; i++ ){
float *f = M[i];
for( int j = 0; j < f[0]; j++ ){
printf("%f\t", f[j + 1]);
}
putchar('\n');
}
}
float *
parse_line(const char *s, int lc)
{
/* Skip the name */
char *end;
while( *s && ! isspace(*s) ){
s += 1;
}
int siz = strtol(s, &end, 10);
if( siz <= 0 || ! isspace(*end) ){
errx(EXIT_FAILURE, "Invalid input on line %d", lc);
}
float *f = xmalloc((1 + siz) * sizeof *f);
f[0] = siz;
for( int i = 1; i < siz + 1; i += 1 ){
f[i] = strtof(end, &end);
}
while( isspace(*end) ){
end += 1;
}
if( *end == '\0' || strcmp(end, "0.00\n") ){
errx(EXIT_FAILURE, "Invalid input on line %d", lc);
}
return f;
}
int
get_row_count(FILE *in, char **line, size_t *cap, const char *name)
{
if( getline(line, cap, in) <= 0 ){
if( feof(in) ){
errx(EXIT_FAILURE, "Empty input");
} else {
err(EXIT_FAILURE, "%s", name);
}
}
char *end;
int rows = strtol(*line, &end, 10);
if( rows <= 0 ){
errx(EXIT_FAILURE, "invalid row count: %d", rows);
}
if( *end != '\n' ){
errx(EXIT_FAILURE, "unexpected input on line 1");
}
return rows;
}
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
*mode == 'r' ? stdin : stdout;
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
void *
xmalloc(size_t s)
{
void *rv = malloc(s);
if( rv == NULL ){
perror("malloc");
exit(EXIT_FAILURE);
}
return rv;
}

matching string pattern flat file in C

Just to have a look a name in a list, when match, the value is discounted.
I tried to code, but the matching technique is fail. Like I try to find "John", but it match with "John" and "Johnny", whether the expected match is just "John" (case is not sensitive)
Just want to help my mom's store.
What I want is something like:
I have 3 set of flat file (list1.txt, list2.txt, list3.txt). Each file has its name, for example:
John
Rudy
Barrack Obama
John Travolta
List2.txt contained:
Jeddi Sarah
Mute Sand
List3.txt contained:
Greedy Black
Nevada Blue
The program when executed, ask:
Enter name: Greedy Black
Enter price: 1000
If the name is listed in list1.txt, he gets discount price 10%, list2.txt for 20%, and list3.txt for 30%.
example output:
Enter name: Greedy Black
Enter price: 1000
Greedy Black is found in list3.txt, got discount for 10%
price after discount: 900
But if he does not in any list, he gets normal price, which is 1000.
How could I do that in C?
Thank you for the help...
This Works Fine
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_C 111
char *trim(char *str);
int countlines(const char *filename);
char ** names(const char *filename);
int contains(const char* a)
{
int l1 = countlines("list1.txt");
int l2 = countlines("list2.txt");
int l3 = countlines("list3.txt");
char** c1 = names("list1.txt");
char** c2 = names("list2.txt");
char** c3 = names("list3.txt");
for (int i = 0; i < l1; ++i) {
if (strcmp(a,c1[i])== 0 )
return 1;
}
for (int i = 0; i < l2; ++i) {
if (strcmp(a,c2[i])== 0 )
return 2;
}
for (int i = 0; i < l3; ++i) {
if (strcmp(a,c3[i])== 0 )
return 3;
}
for (int j = 0; j < l1; ++j) {
printf("%s\t%s",a,c1[j]);
}
return 0;
}
int main()
{
char * a = (char * ) malloc(MAX_C);
printf("Enter Name:\n");
scanf("%[^\n]",a);
int p;
printf("Enter Price:\n");
scanf("%d",&p);
int c = contains(a);
if(c)
{
printf("Greedy Black is found in list%d.txt, got discount for 10%%\nprice after discount: %f",c,p-p/10.0);
}
else
{
printf("Greedy Black is found in list%d.txt, got discount for 10%%\nprice Without discount: %f",c,p);
}
}
int countlines(const char *filename) {
// count the number of lines in the file called filename
FILE *fp = fopen(filename, "r");
int ch = 0;
int lines = 0;
if (fp == NULL)
return 0;
lines++;
while ((ch = fgetc(fp)) != EOF) {
if (ch == '\n')
lines++;
}
fclose(fp);
return lines;
}
char ** names(const char *filename)
{
int line = countlines(filename);
char ** arr = (char **)malloc(line * sizeof(char *));
for (int i=0; i<line; i++)
arr[i] = (char *)malloc(MAX_C * sizeof(char));
FILE * fp = fopen(filename, "r");
if (fp == NULL) {
printf("Could not open file %s", filename);
return NULL;
}
for (int i = 0; i < line; ++i) {
if(fgets(arr[i], MAX_C, fp)!=NULL)
{
trim(arr[i]);
}
}
return arr;
}
char *trim(char *str)
{
size_t len = 0;
char *frontp = str;
char *endp = NULL;
if( str == NULL ) { return NULL; }
if( str[0] == '\0' ) { return str; }
len = strlen(str);
endp = str + len;
/* Move the front and back pointers to address the first non-whitespace
* characters from each end.
*/
while( isspace((unsigned char) *frontp) ) { ++frontp; }
if( endp != frontp )
{
while( isspace((unsigned char) *(--endp)) && endp != frontp ) {}
}
if( frontp != str && endp == frontp )
*str = '\0';
else if( str + len - 1 != endp )
*(endp + 1) = '\0';
/* Shift the string so that it starts at str so that if it's dynamically
* allocated, we can still free it on the returned pointer. Note the reuse
* of endp to mean the front of the string buffer now.
*/
endp = str;
if( frontp != str )
{
while( *frontp ) { *endp++ = *frontp++; }
*endp = '\0';
}
return str;
}

Base change program in C complies but does not show any output

I'm recently new to programming but this assignment has proven to be my most difficult. The program is suppose to read in a .txt file with the following format
input_base number output_base
and outputs the results. the bases can only range from 2-36 For example:
input: 2 10 4
output: 2
My program reads in each part of the line and stores them respectively. I then go through the steps to convert the number into the output base and then print it backwards. My problem is that the program runs fine and prints all the stored values and calculated values, but once I add in my "base_conversion" function the program no longer works and my friend even said it gave him a segmentation fault. I don't really know what could be causing it. Any help would be appreciated. Thank you.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void read_file_to_buffer(FILE *file);
char *buffer = NULL;
void string_check(char *buffer);
int char_to_int(char c);
int int_conversion(int x, int y);
void base_conversion(int end_number, int out_base);
int main(int argc, char *argv[]){
FILE *file = NULL;
if ( argc != 2 ){
fprintf(stderr, "Error: To many/few arguments\n");
exit(EXIT_FAILURE);
}
else {
file = fopen(argv[1], "rb");
if (file == NULL) {
fprintf(stderr, "Error: could not open file '%s'\n", argv[1]);
exit(EXIT_FAILURE);
}
else{
printf("File %s opened!\n", argv[1]);
}
}
read_file_to_buffer(file);
string_check(buffer);
fclose(file);
free(buffer);
buffer = NULL;
exit(EXIT_SUCCESS);
}
void read_file_to_buffer(FILE *file) {
long file_size = 0;
if(buffer != NULL){
fprintf(stderr, "buffer in use\n");
exit(EXIT_FAILURE);
}
rewind(file);
if (fseek(file, 0, SEEK_END) != 0){
perror("Could not seek to end of file");
exit(EXIT_FAILURE);
}
file_size = ftell(file);
if (file_size < 0){
perror("could not tell size of file");
exit(EXIT_FAILURE);
}
rewind(file);
buffer = (char *)malloc(sizeof(char) * (file_size + 1));
if (buffer == NULL){
fprintf(stderr, "Could not allocate memory");
exit(EXIT_FAILURE);
}
if(fread(buffer, sizeof(char), (size_t)file_size, file) != file_size){
fprintf(stderr, "Could not read file\n");
exit(EXIT_FAILURE);
}
buffer[file_size] = '\0';
return;
}
void string_check(char *buffer){
int i = 0;
int j = 0;
char base_in[2];
char number[50];
char base_out[2];
int actual_number[100];
int end_number = 0;
int x = 0;
int y = 0;
int in_base;
int out_base;
while( buffer[i] != '\0'){
if (buffer[i] != '#' && buffer[i] != ' ' && buffer[i] != '\n' && buffer[i] != '\r'){
while (buffer[i] != ' '){
base_in[j] = buffer[i];
i++;
j++;
}
j = 0;
i++;
if (base_in[1] != '\0'){
x = char_to_int(base_in[0]);
y = char_to_int(base_in[1]);
in_base = int_conversion(x, y);
x = 0;
y = 0;
}
else{
in_base = char_to_int(base_in[0]);
}
while (buffer[i] != ' '){
number[j] = buffer[i];
i++;
j++;
}
int q;
q=j;
j=0;
while (number[j] != '\0'){
actual_number[j] = char_to_int(number[j]);
end_number = end_number + pow(in_base, q-1) * actual_number[j];
j++;
q--;
}
j = 0;
i++;
while (buffer[i] != '\n' && buffer[i] != '\0'){
base_out[j] = buffer[i];
i++;
j++;
}
if (base_out[1] != '\0'){
x = char_to_int(base_out[0]);
y = char_to_int(base_out[1]);
out_base = int_conversion(x, y);
x = 0;
y = 0;
}
else{
out_base = char_to_int(base_out[0]);
}
j = 0;
i++;
base_conversion(end_number, out_base);
}
else{
while (buffer[i] != '\n' && buffer[i] != '\0'){
i++;
}
}
i++;
}
return;
}
int char_to_int(char c){
char map[] = "0123456789abcdefghijklmnopqrstuvwxyz";
int result = -1;
char *next = map;
while(*next != '\0'){
if(*next == c){
result = next - map;
break;
}
next++;
}
return result;
}
int int_conversion(int x, int y){
int value;
value = (x * 10) + y;
return value;
}
void base_conversion(int end_number, int out_base){
int remainder[100];
char map[] = "0123456789abcdefghijklmnopqrstuvwxyz";
int index = 0;
int i;
while (end_number != 0){
remainder[index] = end_number % out_base;
end_number = end_number / out_base;
index++;
}
for (i=0; i<index; i++){
printf("%c", map[remainder[index-1]]);
}
printf("\n");
return;
}
OP's base_conversion() is messed.
Loop prints same character repeatedly.
for (i=0; i<index; i++){
printf("%c", map[remainder[index-1]]); // Why same character?
}
Code is using signed math and % and can create negative remainders which may be used as array index.
remainder[index] = end_number % out_base; // result may be negative.
...
printf("%c", map[remainder[index-1]]); // accessing out of bounds with negative
Suggested simplification.
void base_conversion_helper(unsigned end_number, int out_base){
if (end_number >= out_base) base_conversion_helper(end_number/out_base, out_base);
putchar("0123456789abcdefghijklmnopqrstuvwxyz"[end_number % outbase]);
}
void base_conversion(unsigned end_number, int out_base){
assert(out_base >= 2 && out_base <= 36);
base_conversion_helper(end_number, out_base);
putchar('\n');
}

Reading struct from binary file doesn't show it as it should

I have populated a structure with data and wrote it into a binary file. The problem is, when I try to read it back, it doesn't show the structure correctly! Here's the code...
#define MAXS 30
typedef struct {
char id[50];
int pct1, pct2;
} TStudd;
int ReadStruct(FILE* f, TStudd as ){
int i=0;
while (i < MAXS && fscanf(f, "%s" , as.id) == 1)
{
fscanf (f, "%i %i", &as.pct1, &as.pct2);
i++;
}
return i;//total number of read people
}
int WriteBinary(FILE* f, TStudd as){
int pct1, pct2, i;
pct1 = as.pct1;
pct2 = as.pct2;
i = fwrite(as.id, sizeof(as.id), 1,f);
if( i != 1) return -1;
i = fwrite(&pct1, sizeof(pct1), 1,f);
if( i != 1) return -2;
i = fwrite(&pct2, sizeof(pct2), 1,f);
if( i != 1) return -3;
return 0;
}
int ReadBinary(FILE* f){
char id [50];
int pct1, pct2, i;
i = fread(id, sizeof(id), 1,f);
if( i != 1) return -1;
printf("%s", id);
i = fread(&pct1, sizeof(pct1), 1,f);
if( i != 1) return -2;
printf("%i", pct1);
i = fread(&pct2, sizeof(pct2), 1,f);
if( i != 1) return -3;
printf("%i", pct2);
return 0;
}
g = fopen(sursa, "rt");
v = ReadStruct(g, ps);
printf("%i\n", v);
f = fopen(dest, "w+b");
}
if ( ReadBinary(f, ps) < 0){
printf("Eroare scriere\n");
return 1;
}
if ( WriteBinary(f) < 0 ){
printf("Eroare citire\n");
return 1;
};
fclose(g);
fclose(f);
What should I change? Thank you!
Platform is Windows 7 64 bit and the file isn't subject to any conversion (just writing and reading stuff from it)

Resources