Problem with File I/O in C Programming Language - c

I am writing a program to create a file of prime numbers.
I am new to C, and thus to its I/O system.
The input is the number before (and including) which all prime numbers are to be written in a prime.csv file. I am trying to make my code efficient by using old primes. But, the subsequent prime of the last prime in the prime.csv file is not being appended. I have been stuck on this problem for a while now. Any help will be appreciated.
primes.c:
#include <stdio.h>
#include <stdlib.h>
int isPrime(FILE *file, unsigned int length, unsigned int number);
void primes(unsigned int number);
int main(int argc, char *argv[])
{
if (argc != 2)
{
perror("Usage: a.exe number");
return 1;
}
unsigned int number = atoi(argv[1]);
primes(number);
return 0;
}
int isPrime(FILE *file, unsigned int length, unsigned int number)
{
fseek(file, 0L, SEEK_SET);
unsigned int factor;
for (int i = 0; i < length; i++)
{
fscanf(file, "%u", &factor);
if (number % factor == 0)
return 0;
}
return 1;
}
void primes(unsigned int number)
{
// Getting Header Info
FILE *file_h = fopen("primes_h.csv", "r");
if (file_h == NULL)
{
perror("Was not able to open the file");
return;
}
unsigned int length;
unsigned int last;
fscanf(file_h, "%u,%u", &length, &last);
fclose(file_h);
// If number already less than or equal to last prime
if (number <= last + 1)
{
puts("Condition already satisfied.");
return;
}
// Adding new primes
FILE *file = fopen("primes.csv", "a+");
if (file == NULL)
{
perror("Was not able to open the file");
return;
}
unsigned int newLast;
unsigned int newLength = length;
for (unsigned int now = last + 2; now <= number; now += 2)
{
if (isPrime(file, newLength, now))
{
fprintf(file, "%u\n", now);
newLast = now;
newLength++;
}
}
fclose(file);
// Editing Header Info
FILE *e_file_h = fopen("primes_h.csv", "w");
if (e_file_h == NULL)
{
perror("Was not able to open the file");
return;
}
fprintf(e_file_h, "%u,%u", newLength, newLast);
fclose(e_file_h);
}
primes.csv:
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
101
103
107
109
and so on...
primes_h.csv:
669,4999
The primes_h.csv contains the header info about the primes.csv in the format: length, last

Reading primes from a file to test a number for primality is very inefficient: you will save a number of divisions, but these savings should be small compared to the overhead of reading from the file system and converting the numbers from text to internal representation. Furthermore, you should stop trying the divisors when they become greater than the square root of the number.
You could instead use an array to store the prime numbers found so far. This array does not need to store more than the prime numbers below the square root of the maximum number.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int primes[46341]; // all primes up to sqrt(INT32_MAX)
int nprimes = 0;
if (argc < 2) {
fprintf(stderr, "primes: missing argument\n");
return 1;
}
int limit = strtol(argv[1], NULL, 0);
FILE *fp = fopen("primes.csv", "w");
if (fp == NULL) {
fprintf(stderr, "primes: cannot open primes.csv\n");
return 1;
}
fprintf(fp, "prime\n");
if (limit >= 2) {
primes[nprimes++] = 2;
fprintf(fp, "2\n");
}
for (int n = 3; n <= limit; n += 2) {
int isprime = 1;
for (int i = 1; i < nprimes; i++) {
int p = primes[i];
if (p * p > n)
break;
if (n % p == 0) {
isprime = 0;
break;
}
}
if (isprime) {
if (nprimes < (int)(sizeof(primes) / sizeof(primes[0])))
primes[nprimes++] = n;
fprintf(fp, "%d\n", n);
}
}
fclose(fp);
return 0;
}
Note however that trial division is not very efficient to enumerate primes numbers up to a limit. A Sieve of Eratosthenes is much faster.

Related

How can I add together the numbers in a file?

I have a large text file. In this file there are some numbers I want to add together.
What I've tried:
int sum = 0, i = 0;
file = fopen(filename, "r");
while ((i = fgetc(file)) != EOF) {
if (isdigit(i)) {
sum++;
}
}
printf("Sum of numbers is: %i", sum);
fclose(file);
But that isdigit(i) is just a counter of how many digits this file contains, not what the sum of the numbers is.
The input is: "This text 15 is very 19 nice."
The result should be: Sum of numbers is: 34
Consider the decimal placement
The missing part in the question's code is accumulating the digits (as opposed to counting the digits with sum++;) AND multiplying by ten the previous accumulated number before adding the next digit.
The answer is in:
number = number * 10 + i - '0';
The - '0' part is converting ASCII digit to a number.
Everything else in the below code is checks to make sure there are no obvious overflows and correctly supporting minus sign also adjacent to the numbers, as well as ignoring digits after the decimal point(s). I'm sure it is not perfect, but the idea here is to provide a working example of how it could be done, rather than a well tested code and using a library call to do it for you.
By popular demand (comments were deleted now) I've added a simple-but-working overflow check:
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <error.h>
#include <limits.h>
int main(int argc, char* argv[]) {
int sum = 0, state = 0, i = 0, dir = 1;
unsigned int number = 0, check;
if (argc < 2) {
fprintf(stderr, "Missing filename\n");
return EXIT_FAILURE;
}
char* filename = argv[1];
FILE* file = fopen(filename, "r");
if (!file) {
perror(filename);
return EXIT_FAILURE;
}
while (i != EOF) {
i = fgetc(file);
if (isdigit(i)) {
if (dir) {
state = 1;
check = number;
number = number * 10 + i - '0';
if (check > number || number > INT_MAX) {
fprintf(stderr, "Single number overflow error\n");
fclose(file);
return EXIT_FAILURE;
}
}
} else {
if (state && dir) {
check = number;
if (dir < 0 && sum < 0)
check -= sum;
else if (dir > 0 && sum > 0)
check += sum;
if (check > INT_MAX) {
fprintf(stderr, "Sum overflow error\n");
fclose(file);
return EXIT_FAILURE;
}
sum += number * dir;
number = 0;
}
state = 0;
dir = i == '-' ? -1 : i == '.' ? 0 : 1;
}
}
printf("Sum of numbers is: %i\n", sum);
fclose(file);
return EXIT_SUCCESS;
}
Test run:
$ cat opString.txt
This text 15 is very 19 nice.
$ ./test2 opString.txt
Sum of numbers is: 34
$
And just in case you are on 64bit linux system, and need much higher performance (you mentioned large file) the below code will map the entire file (even file larger than memory, the kernel will handle it nicely) and will not make a library call on every char. In my tests, isdigit() and strtol() slows it down significantly.
#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <limits.h>
#include <sys/mman.h>
int addToSum(unsigned int* number, int* sum, int dir, FILE* file) {
unsigned int check;
check = *number;
if (dir < 0 && *sum < 0)
check -= *sum;
else if (dir > 0 && *sum > 0)
check += *sum;
if (check > INT_MAX) {
fprintf(stderr, "Sum overflow error\n");
fclose(file);
exit(EXIT_FAILURE);
}
*sum += *number * dir;
*number = 0;
}
int main(int argc, char* argv[]) {
int sum = 0, state = 0, i = 0, dir = 1;
unsigned int number = 0, check;
if (argc < 2) {
fprintf(stderr, "Missing filename\n");
return EXIT_FAILURE;
}
char* filename = argv[1];
FILE* file = fopen(filename, "r");
if (!file) {
perror(filename);
return EXIT_FAILURE;
}
if (fseek(file, 0L, SEEK_END) < 0) {
perror("fseek failed");
fclose(file);
return EXIT_FAILURE;
}
long fsize = ftell(file);
char* fmap = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fileno(file), 0);
if (fmap == MAP_FAILED) {
perror("map failed");
fclose(file);
return EXIT_FAILURE;
}
long pos = 0;
while (pos < fsize) {
i = fmap[pos++];
if (i >= '0' && i <= '9') {
if (dir) {
state = 1;
check = number;
number = number * 10 + i - '0';
if (check > number || number > INT_MAX) {
fprintf(stderr, "Single number overflow error\n");
fclose(file);
return EXIT_FAILURE;
}
}
} else {
if (state && dir) addToSum(&number, &sum, dir, file);
state = 0;
dir = i == '-' ? -1 : i == '.' ? 0 : 1;
}
}
if (state && dir) addToSum(&number, &sum, dir, file);
printf("Sum of numbers is: %i\n", sum);
fclose(file);
return EXIT_SUCCESS;
}
Input file name: file.txt
This text 15 is very 19 nice.
Output:
Sum of numbers is: 34
Code:
#include <stdio.h>
#include <ctype.h>
int main()
{
int sum = 0, num, i = 0;
int state = 0;
FILE* f;
if ((f = fopen("file.txt", "r")) == NULL)
return -1;
while ((i = fgetc(f)) != EOF) {
switch(state) {
case 0: // processing text
if (isdigit(i)) {
num = i - '0';
state = 1;
}
break;
case 1: // processing number
if (isdigit(i)) {
num *= 10;
num += i - '0';
}
else {
sum += num;
num = 0;
state = 0;
}
break;
}
}
if (state == 1) {
sum += num;
}
printf("Sum of numbers is: %i\n", sum);
fclose(f);
return 0;
}
But that isdigit(i) is just a counter of how many digits this text contents but not whats the sum of the numbers is.
Keep in mind, the function isdigit() reads one character per call. So if it reads the character 9 for example, the value sum should grow by i - '0' (or 57 - 48, or 9). And if there were two characters in sequence, such as 92, reading one character at a time, the value sum would likewise be incremented by 9+2 -> 11, not 92. Given this is what you want, here is how to do it:
The values you have determined are digits are actually ASCII values, so in viewing this table you can see all of the digits will have values from '0' to '9' (or in ASCII, 48 to 57). So in your code you can simply change one line to sum up the value count:
int sum = 0;
file = fopen(filename, "r");
while ((i = fgetc(file)) != EOF) {
if (isdigit(i))
sum += (i - '0');//subtract 48 from every 'i' verified as digit
//Sum will therefore add up values
//between (48-48) to (57-48)
//(or between 0 to 9)
}
printf(f,"Sum of numbers is: %i", sum);
fclose(file);
However, If you want to sum up numeric values represented by a sequence of digits within a buffer, then the code is different. It would require keeping a flag as the buffer content is read.
In pseudo code:
char accumlator[10] = {0}; max possible sequential digits (change as needed)
int found = 0;//flag
int sum = 0;
while ((i = fgetc(file)) != EOF)
{
if (isdigit(i))
{
accumulator[found] = i;
found++;
}
else
{
if(found != 0)
{
sum += atoi(accumulator);
found = 0;
accumulator[0] = 0;
}
}
}
}
The function fgetc only reads a single character that is a potential digit. It does not read a whole number that consist of several digits at once. If you want to read whole numbers, you must change the logic of your program. You can do one of the following:
Use fgetc as you do now and make your program assemble the individual digits into a number, by using the ASCII Code of the digits and converting that to a number using arithmetic. The numerical value of an individual ASCII character digit can be obtained using the expression ascii_code - '0'.
Use fgets instead to read a whole line at once and then use strtol to convert any digits you find into numbers.
Use fscanf() to parse the file and extract the number in one step (not recommended unless you know exactly what you are doing).
Your program only counts the number of digits in the file. Here is a simple solution using getc() to compute the number of all integral numbers in the file without the need for a state machine:
#include <stdio.h>
int count_numbers(const char *filename) {
FILE *fp;
unsigned long long total = 0, current = 0;
int c;
if ((fp = fopen(filename, "r")) == NULL) {
printf("Cannot open input file %s\n", filename);
return -1;
}
while ((c = getc(fp)) != EOF) {
if (c >= '0' && c <= '9') {
current = current * 10 + (c - '0');
} else {
total += current;
current = 0;
}
}
total += current; /* add the last number if at the very end of the file */
printf("Sum of numbers is: %llu\n", total);
fclose(fp);
return 0;
}
Notes:
this program does not handle negative numbers, it ignores negative signs.
it does not handle floating point numbers: processing 1.1 will produce a sum of 2.
very long numbers will produce the result modulo ULLONG_MAX+1 but at least the behavior is defined.
If you want to add all the number strings up in this then you'll have to search for the digits and then convert them from a string to an integer using strtol. Here's how to do that:
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#define OVERFLOW_STR "Number cannot be represented in an int!\n"
int main(int argc, char **argv)
{
FILE *file;
char n[12];
char *p = n;
int i = 0, sum = 0, tmp, old_errno;
if(argc != 2)
{
fprintf(stderr, "Usage: %s file\n", argv[0]);
return EXIT_FAILURE;
}
file = fopen(argv[1], "r");
if(!file)
{
perror("Error opening file");
return EXIT_FAILURE;
}
while(i != EOF)
{
while( (i = fgetc(file)) != EOF &&
i != '-' &&
i != '+' &&
!isdigit(i) )
{
/* empty loop */ ;
}
if(i != EOF)
{
do {
if( p == n + sizeof(n) - 1 ||
((*n != '-' || *n != '+') &&
p == n + sizeof(n) - 2) )
{
fprintf(stderr, "Error: " OVERFLOW_STR);
return EXIT_FAILURE;
}
*p++ = i;
} while( (i = fgetc(file)) != EOF && isdigit(i) );
}
else
break;
*p = 0;
old_errno = errno;
errno = 0;
tmp = strtol(n, NULL, 10);
if( tmp == 0 && errno != 0 )
{
perror("Error converting string");
break;
}
errno = old_errno;
sum += tmp;
p = n;
}
printf("Sum of numbers is: %d\n", sum);
fclose(file);
return 0;
}
This is largely error-checked. There may be corner cases that I have left out.
Input (contained in a file whose name is passed as a command-line parameter):
This text 15 is very 19 nice.
Output:
Sum of numbers is: 34

Reading in Large Integer txt file into 2D array

Attempting to create a program that reasons in a large Text File and filled them into Rows + Columns. Eventually I'll have to computer best path but having trouble just implementing an Array that can store the values.
#include <stdio.h>
#include <stdlib.h>
//max number of characters to read in a line. //MAXN=5 means 4 chars are read, then a \0 added in fgets. See reference for functionality
#define MAXN 100L
int main(void) //char** argv also ok {
int i=0, totalNums, totalNum,j=0;
size_t count;
int numbers[100][100];
char *line = malloc(100);
FILE* inFile ;
inFile = fopen("Downloads/readTopoData/topo983by450.txt", "r"); //open a file from user for reading
if( inFile == NULL) { // should print out a reasonable message of failure here
printf("no bueno \n");
exit(1);
}
while(getline(&line,&count, inFile)!=-1) {
for(;count>0; count--,j++)
sscanf(line, "%d", &numbers[i][j]);
i++;
}
totalNums = i;
totalNum = j;
for(i=0;i<totalNums; i++){
for(j=0;j<totalNum;j++){
printf("\n%d", numbers[i][j]);
}
}
fclose(inFile);
return 0;
}
count does not tell you how many numbers there are. Further: sscanf(line, "%d", &numbers[i][j]); will just scan the same number every time.
So this
for(;count>0; count--,j++)
sscanf(line, "%d", &numbers[i][j]);
should be something like:
j = 0;
int x = 0;
int t;
while(sscanf(line + x, "%d%n", &numbers[i][j], &t) == 1)
{
x += t;
++j;
}
where x together with %n helps you move to a new position in the string when a number has been scanned.
Here is a simplified version that scans for numbers in a string:
#include <stdio.h>
int main(void) {
char line[] = "10 20 30 40";
int numbers[4];
int j = 0;
int x = 0;
int t;
while(j < 4 && sscanf(line + x, "%d%n", &numbers[j], &t) == 1)
{
x += t;
++j;
}
for(t=0; t<j; ++t) printf("%d\n", numbers[t]);
return 0;
}
Output:
10
20
30
40

Split a file of text at delimiters and separate integers and text in c

I am reading text from an input file in. I have to separate text from scores ie
John Doe 100 95 67 85
jane doe 67 78 99
and then average the numbers. I can separate by the spaces using strtok but how can i tell when i have an integer? i need to split the reading of names and of integers into 2 functions. My code to read it works but i need to stop at the end of each name. I attempted to use numbers converted to strings and using strcmp however it did not work.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void read_reverse_write(FILE * ptr_file, FILE * op);
void write_and_avarage(int * fp, char * op);
//int checker(char *token);
int main(int argc, char** argv) {
FILE *fp;
FILE *op;
//opens quiz and checks and checks to make sure it did
fp = fopen("quiz.txt", "r");
if (fp == NULL) {
printf("Error opening file");
return (-1);
}
//opens op and checks that it did
op = fopen("output.txt", "w");
if (op == NULL) {
printf("Error opening file");
return (-1);
}
// runs read reverse write
read_reverse_write(fp, op);
fclose(fp);
fclose(op);
return (EXIT_SUCCESS);
}
void read_reverse_write(FILE * ptr_file, FILE * op) {
char buf[1000];
char *token;
const char delim[2] = " ";
fgets(buf, 1000, ptr_file);
token = strtok(buf, delim);
while (token != 100) {
fprintf(op, "%s ", token);
token = strtok(NULL, delim);
}
}
/*void write_and_avarage(int * fp, char * op) {
}
int checker(char *token) {
char *arr[102];
char ph[4];
for (int p = 0; p < 100; p++) {
if (p < 10) {
snprintf(ph, 1, "%d", p);
arr[p] = ph;
} else if (p < 99) {
snprintf(ph, 2, "%d", p);
arr[p] = ph;
} else if (p = 100) {
snprintf(ph, 3, "%d", p);
arr[p] = ph;
}
}
for (int z = 0; z < 100; z++) {
if (strcmp(token, arr[z]) == 1) {
return 1;
} else {
z++;
}
return 0;
}
}
*/
You can use the following code to check the whether the string is a number or not.
#include <stdio.h>
#include <string.h>
#define MAX_NUM 9
#define MIN_NUM 0
#define ZERO 0
#define MAX_SIZE 1024
int checkDigit(int num, int len)
{
int divisor = 1, checkVal = 0;
if(len <= 2)
divisor = 10;
else if(len > 2)
{
len = len - 1;
while(len != ZERO)
{
divisor = divisor * 10;
len = len - 1;
}
}
checkVal = num/divisor;
if(checkVal > MIN_NUM && checkVal <= MAX_NUM)
return 1;
else
return 0;
}
void main()
{
char array[MAX_SIZE] = "JOHN DOE 120 DOE HELLO 2323 90909";
char *split_token = NULL;
int status = 2, len = 0, sum = 0, total_digits = 0;
float average = 0;
split_token = strtok(array, " ");
while( split_token != NULL )
{
len = strlen(split_token);
status = checkDigit(atoi(split_token), len);
if (1 == status)
{
sum = sum + atoi(split_token);
total_digits = total_digits + 1;
}
split_token = strtok(NULL, " ");
}
average = (float)sum/total_digits;
printf("Average is : %f\n", average);
}
This code will check whether your string is a number or not and finally calculate the average of all the numbers in the given string.
If you need to read from a file, multiple sets of inputs, use fscanf() and use the complete code logic repeatedly for each line of input.
Hope it helps! Do ask if you need the complete code or any clarification for the code.

How do I convert from unsigned char to long

I have a problem to convert from unsigned char into long.
The mission: I have 25 in (unsigned char) ptr->studentArr[i].subjectStatus when i = 0, I go into the function unsigned char fromDecToBinary(unsigned char tmpSubjectStatus), and I want in that function to get unsigned long 11001 into variable ret and then fprintf it into output.txt file.
Expectation: to fprintf into the file 11001 when i = 0, problem: it prints 25 instead(if I use fromDecToBinary function, it prints 0).
Please, just look at the 2 functions: outPutStudents and fromDecToBinary, other functions work properly, and those other functions just get the information and store the info. into structures which are then used to print the details into output.txt, most of them work, except the binary thingy.
input.txt file:
Nir 32251 99.80 11001
Ely 12347 77.89 01111
Moshe 45321 50.34 11111
Avi 31456 49.78 00011
*NOTE: this is the output without using the function fromDecToBinary
output.txt file:
Student 1: Nir 32251 99.80 25
Student 2: Ely 12347 77.89 15
Student 3: Moshe 45321 50.34 31
Student 4: Avi 31456 49.78 3
Code:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
typedef struct Student{
char* studentName; //Dyn. alloc. of stud. name
long id; // ID Number
float mark; // mark
unsigned char subjectStatus;
}Student;
typedef struct University{
Student* studentArr; // Dync. Alloc(Realloc) of students
int numOfStudents; //num of students
}University;
void getStudents(University *ptr);
unsigned char stringToBinary(unsigned char tmpSubjectStatus[]);
void outPutStudents(University *ptr);
unsigned char fromDecToBinary(University *ptr);
void main()
{
printf("Please enter details of student: (a)");
University uni;
getStudents(&uni); //Send address of structure University, because we want to change it not make a local copy of it
outPutStudents(&uni);
getch();
}
void getStudents(University *ptr)
{
FILE *op;
char tmpStudentName[20];
long tmpId;
float tmpMark;
char tmpSubjectStatus[6];
ptr->numOfStudents = 0;
if ((op = fopen("input.txt", "r")) == NULL)
{
printf("Failed to open file.");
}
ptr->studentArr = (Student*)malloc(sizeof(Student));
if (ptr->studentArr == NULL){
printf("Error: memory was not allocated.");
exit(1);
}
while (fscanf(op, "%s %ld %f %s", tmpStudentName, &tmpId, &tmpMark, tmpSubjectStatus) == 4)
{
ptr->numOfStudents++;
ptr->studentArr = (Student*)realloc(ptr->studentArr, sizeof(Student) * ptr->numOfStudents); /*Additional code for Realloc fails - we didn't study!*/
ptr->studentArr[ptr->numOfStudents - 1].studentName = (char*)malloc(sizeof(char)* strlen(tmpStudentName));
if (!(ptr->studentArr[ptr->numOfStudents - 1].studentName)) //if we failed to allocate memory for studentName
{
while (ptr->numOfStudents > 0)
{
free(ptr->studentArr[ptr->numOfStudents - 1].studentName); //free student name
ptr->numOfStudents--; // decrease numOfStudents by one
}
free(ptr->studentArr); //if all student names are free, we need to free the array
printf("Student name was not allocated.");
exit(1);
}
strcpy(ptr->studentArr[ptr->numOfStudents - 1].studentName, tmpStudentName);
ptr->studentArr[ptr->numOfStudents - 1].id = tmpId;
ptr->studentArr[ptr->numOfStudents - 1].mark = tmpMark;
ptr->studentArr[ptr->numOfStudents - 1].subjectStatus = stringToBinary(tmpSubjectStatus); //atoi: from "11001"(string) to 11001(int),then casting to unsigned char
}
fclose(op);
}
void outPutStudents(University *ptr)
{
int i;
FILE *fp;
unsigned char tmpSubjectStatus;
long val;
if ((fp = fopen("output.txt", "w")) == NULL)
{
printf("Couldn't open output file.");
exit(1);
}
for (i = 0; ptr->numOfStudents != i; i++){
tmpSubjectStatus = ptr->studentArr[i].subjectStatus;
val = fromDecToBinary(tmpSubjectStatus);
fprintf(fp, "Student %d: %s %ld %.2f %ld \n", i + 1, ptr->studentArr[i].studentName, ptr->studentArr[i].id, ptr->studentArr[i].mark, tmpSubjectStatus);
}
fclose(fp);
}
unsigned char stringToBinary(char tmpSubjectStatus[])
{
unsigned char tmpBinaryCh = 0;
int i;
for (i = 0; i < 5; i++){
if (tmpSubjectStatus[i] == '1') tmpBinaryCh += 1 << (4 - i);
}
return tmpBinaryCh;
}
unsigned char fromDecToBinary(unsigned char tmpSubjectStatus)
{
int i;
long ret;
char arrBinary[6];
for (i = 0; i < 5; i++){
arrBinary[4 - i] = tmpSubjectStatus % 2;
tmpSubjectStatus /= 2;
}
arrBinary[5] = '/0';
ret = strtol(arrBinary, NULL, 10);
return ret;
}
You have several errors in the fromDecToBinary function:
Replace the '/0' with '\0'.
Store '0' + tmpSubjectStatus % 2 in the array.
Add proper error handling to the strtol call.
Change the return type to long.
If you want to print some binary using numbers use this.
#include <stdio.h>
#include <stdlib.h>
void print_bin(uint64_t num, size_t bytes) {
int i = 0;
for(i = bytes * 8; i > 0; i--) {
(i % 8 == 0) ? printf("|") : 1;
(num & 1) ? printf("1") : printf("0");
num >>= 1;
}
printf("\n");
}
int main(void) {
int arg = atoi("25");
print_bin(arg, 1);
return 0;
}
It also prints a vertical bar every 8 bits to make the bytes easier to read but you can just remove that.
If you want to specify how many bytes you want use this
#include <stdio.h>
#include <stdlib.h>
void print_bin(uint64_t num, size_t bytes) {
int i = 0;
for(i = bytes * 8; i > 0; i--) {
(i % 8 == 0) ? printf("|") : 1;
(num & 1) ? printf("1") : printf("0");
num >>= 1;
}
printf("\n");
}
int main(void) {
print_bin(16000, 3);
return 0;
}
#include <stdio.h>
int main()
{
unsigned char tmpSubjectStatus=25;
long quotient = tmpSubjectStatus;
long remainder;
long binary=0;
long multiplier=1;
while(quotient!=0){
remainder=quotient % 2;
binary=binary+(remainder*multiplier);
multiplier=multiplier*10;
quotient = quotient / 2;
}
printf("%ld",binary);
return 0;
}
Try this.
In the function it will be like this
long fromDecToBinary(unsigned char tmpSubjectStatus)
{
long quotient = tmpSubjectStatus;
long remainder;
long binary=0;
long multiplier=1;
while(quotient!=0){
remainder=quotient % 2;
binary=binary+(remainder*multiplier);
multiplier=multiplier*10;
quotient = quotient / 2;
}
return binary;
}
In here return type is changed to long.

C issue with dynamically allocating array

The input file for my program has the first line containing an int (call it N) that will signify how many following integers there will be (each integer on a new line). Then it should read the integers into num_array and print them out. My issue is that num_array is not being allocated properly I think. The debugging statements in the code will print out 8 being the sizeof(num_array) no matter what N is.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
int *num_array;
int main (int argc, char**argv){
int numThreads = (int) argv[1];
char *inputFile = argv[2];
int N = 0;
char line[20];
FILE *file = fopen(inputFile, "r");
int fileCounter = 0;
while(fgets(line, sizeof(line), file)) {
if (fileCounter==0){
N = atoi(line);
num_array = malloc(sizeof(int)*(N+1));
}
else{
num_array[fileCounter-1] = atoi(line);
}
fileCounter++;
}
fclose(file);
int i;
printf("%d", sizeof(num_array));
printf("\n");
printf("\n");
for(i = 0; i<sizeof(num_array); i++){
printf("%d\n", num_array[i]);
}
return 0;
}
Input file example:
9
10
9
3
212
56
99
4
5
6
will print out:
8
10
9
3
212
56
99
4
5
As you can see, the last element of the array is cut off (does not print 6) and it appears num_array is not being sized properly (should contain N integers with N being the int at the first line of the input file)
Many problems with your program:
The first line of your main() function has a very severe mistake
int numThreads = (int) argv[1]
in c casting does not convert the type, this conversion is certainly possible, but doesn't give the result you expect, you need something like this
char *endptr;
int numThreads = strtol(argv[1], &endptr, 10);
if (*endptr != '\0')
{
printf("`%s' cannot be converted to an integer\n", argv[1]);
return -1;
}
You didn't make sure that there was a parameter provided to your program's command line, you need to check that, argc contains the number of command line arguments passed to your program + the argv[0], so you must check
if (argc < 2)
{
printf("Use: %s NumberOfThreads, where NumberOfThreads is `int'\n", argv[0]);
return -1;
}
You don't check if fopen() returns NULL, that would cause more issues when you fgets() the file pointer.
The sizeof operator does not give the length of an array it gives the number of bytes occupied by the array, and you variable is not an array, it's a pointer, so the sizeof operator in this case is giving the size of a pointer.
It turns out that your file contains 9 values and in your platform the pointer size is 8, so sizeof(num_array) is 8 which is 9 - 1 hence your are missing one value, you already have the number of elements of the array N, so use it.
You never call free().
This is a version of your code, it's fixed and it's made safer
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
int *num_array;
int main (int argc, char**argv)
{
char line[20];
/*int numThreads = 1;*/
char *inputFile = "data.dat";
int N = 0;
int fileCounter = 0;
int i = 0;
FILE *file = fopen(inputFile, "r");
if (file == NULL)
return -1;
while (fgets(line, sizeof(line), file) != NULL)
{
if (fileCounter == 0)
{
N = atoi(line);
num_array = malloc((1 + N) * sizeof(int));
if (num_array == NULL)
{
fclose(file);
return -1;
}
}
else
{
num_array[fileCounter - 1] = atoi(line);
}
fileCounter++;
}
fclose(file);
printf("%ld", sizeof(num_array));
printf("\n");
printf("\n");
for (i = 0 ; i < N ; i++)
{
printf("%d\n", num_array[i]);
}
free(num_array);
return 0;
}

Resources