Transfer results to txt file C - c

so i'm completely new to programming (i've been learning for 3 days) and i find myself infront of a problem i simply don't know how to resolve.
I want this program to give me every single combination from 0 to a specific number in base 36. That is easy enough when the number is only about 50000 or so. But my goal from this is to extract actual words(with numbers too) and if i try to get words with 5 characters, the terminal will start overwriting the previous words(not helpful, i want ALL of them).
So i thought i should look for a way to transfer everything into a txt file and there resides my problem: I don't know how... Sorry for the long text but i wanted to explain precisely what i'm trying to get. Thanks for the help.
int main() {
int dec, j, i, q, r, k;
char val[80];
printf("Enter a decimal number: ");
scanf("%d", &dec);
for (k = 0; k <= dec; k++) { /*repeat for all possible combinations*/
q = k;
for (i = 1; q != 0; i++) { /*convert decimal number to value for base 36*/
r = q % 36;
if (r < 10)
r = r + 48;
else
r = r + 55;
val[i] = r;
q = q / 36;
}
for (j = i - 1; j > 0; j--) { /*print every single value*/
printf("%c", val[j]);
}
printf(" "); /*add spaces because why not*/
}
return (0);
}

A few observations that might help:
First is type related:
In your declarations you create the following:
int dec, j, i, q, r, k;
char val[80];
Then later you make the assignment:
val[i] = r;//assigning an int to a char, dangerous
While r is type int with a range (typically) of –2,147,483,648 to 2,147,483,647,
val[i] is of type char with a range (typically) of only –128 to 127.
Because of this, you may run into an overflow, leading to unexpected results.
The most immediate solution is use the same type for both variables. Pick either int or char, but not both.
The other has already been addressed correctly by #Nasim. Use the file version of printf() - fprintf(). As the link shows, the prototype for fprintf() is:
int fprintf( FILE *stream, const char *format [, argument ]...);
Usage example:
FILE *fp = fopen(".\somefile.txt", "w");//create a pointer to a FILE
if(fp)//if the FILE was successfully created, write to it...
{
// some of your previous code...
for (j = i - 1; j > 0; j--)
{ /*print every single value*/
fprintf(fp, "%c", val[j]);//if val is typed as char
//OR
fprintf(fp, "%d", val[j]);//if val is typed as int
}
fclose(fp);
}
Lastly, there are a wide range of methods to perform base conversion. Some more complicated than others.

create a file and then you can use fprintf() instead of printf the only difference between the two is that you need to specify the file as an argument
FILE *myFile = fopen("file.txt", "w"); //"w" erase previous content, "a" appends
If(myFile == NULL) {printf("Error in openning file\n"); exit(1);}
fprintf(myFile, "some integer : %d\n", myInteger); // same as printf my specify file pointer name in first argument
fclose(myFile); //dont forget to close the file

Related

Access Binary form of Text saved in memory using an Array

The storage representation of the string or equivalently text from a file, is the ASCII code for each character of the string or text from a file, I have been told that I/O functions like fread and fgets will read a string from disk into memory without conversion. The C compiler always works with the storage representation, so when we "retrieve" a string in C, it's always in binary form.
I need to access this binary form to use in my code (without saving this as a binary file, also not asking to print in binary format).
For example, the text string "AA" is saved in memory as "0100000101000001", I need to access directly, without any conversion (like we do when we print, integer using %s, %d) this binary form "0100000101000001" of "AA" using an integer array, say, D[16] which has elements 0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1. So if I use an index int i, I will get 0 from D[4] for i=0.
Array-index operations like buffer[i] (for example, in the sample code in the below) will extract one character from a string:
FILE *fp = fopen("a.txt", "r");
if (fp == NULL)
return 1;
char buffer[100];
int r = fread(buf, 1, sizeof(buffer), fp);
if (r <= 0)
return 1;
printf("As string: %.*s", r, buffer);
printf("As integers:");
for (i = 0; i < r; i++)
printf(" %d", buffer[i]);
But I would like to have the complete text as an array of 0 and 1, whereas here, buffer[i] contains 8 bits which I cannot access individually each bit, how can I do that?
I have been told that I/O functions like fread and fgets will read a string from disk into memory without conversion.
This is true if the file has been open as binary, ie: with "rb". Such streams do not undergo any translation when read into memory, and all stream functions will read the contents as it is stored on disk, getc() included. If your system is unix based, there is no difference with "r", but on legacy systems, there can be substantial differences: text mode, which is the default, may imply end of line conversion, code page translation, end of file mitigation... If you want the actual file contents, always use binary mode ("rb").
You should also avoid the char type when dealing with binary representation, because char is signed by default on many architectures, hence inappropriate for byte values which are usually considered positive. Use unsigned char to prevent this issue.(*)
The most common way to display binary contents is using hexadecimal representation, where each byte is output as exactly 2 hex digits.
If you want to output binary representation, there is no standard printf conversion to output base-2 numbers, but you can write a loop to convert the byte to its bit values.
(*) among other historical issues such as non two's complement signed value representations
Here is a modified version:
#include <stdio.h>
int main() {
FILE *fp = fopen("a.txt", "r");
if (fp == NULL) {
perror("a.txt");
return 1;
}
unsigned char buffer[100];
unsigned char bits[100 * 8];
int r = fread(buffer, 1, sizeof(buffer), fp);
if (r <= 0) {
fprintf(stderr, "empty file\n");
fclose(fp);
return 1;
}
printf("As a string: %.*s\n\n", r, (char *)buffer);
int pos;
pos = printf("As 8-bit integers:");
for (int i = 0; i < r; i++) {
if (pos > 72) {
printf("\n");
pos = 0;
}
pos += printf(" %d", buffer[i]);
}
printf("\n\n");
pos = printf("As hex bytes:");
for (int i = 0; i < r; i++) {
if (pos > 72) {
printf("\n");
pos = 0;
}
pos += printf(" %02X", buffer[i]);
}
printf("\n\n");
pos = printf("Converting to a bit array:");
for (int i = 0; i < r; i++) {
for (int j = 8; j-- > 0;) {
bits[i * 8 + 7 - j] = (buffer[i] >> j) & 1;
}
}
/* output the bit array */
for (int i = 0; i < r * 8; i++) {
if (pos > 72) {
printf("\n ");
pos = 4;
}
pos += printf("%d", bits[i]);
}
printf("\n");
fclose(fp);
return 0;
}
Use bit masking to check the value of individual bits. Checkout a brief description here https://www.learn-c.org/en/Bitmasks
Then you can write the result to your array for the corresponding bit.

Not able to print this 2D array (weird output) in C

I am trying to read a text file with 100 numbers like 1 2 45 55 100 text file here (all on a single line) and then put them in a 10x10 array (2D array).
736.2 731.6 829.8 875.8 568.3 292.2 231.1 868.9 66.7 811.9 292.0 967.6 419.3 578.1 322.5 471.7 980.0 378.8 784.1 116.8 900.4 355.3 645.7 603.6 409.1 652.1 144.1 590.6 953.1 954.0 502.0 689.3 685.6 331.9 565.1 253.9 624.1 796.2 122.8 690.7 608.0 414.8 658.3 27.3 992.9 980.8 499.0 972.8 359.7 283.1 89.7 260.1 638.4 735.4 863.6 47.5 387.5 7.7 638.1 340.6 961.7 140.1 29.8 647.3 471.9 594.9 901.2 96.0 391.1 24.0 786.7 999.1 438.7 445.0 26.4 431.6 425.9 525.4 404.4 785.6 808.5 494.1 45.7 447.0 229.5 909.3 494.4 617.0 917.0 132.5 957.5 878.8 272.6 987.4 526.1 744.5 582.3 427.3 840.5 973.3
Here is my code:
#include <stdio.h>
#define NR 10
#define NC 10
int main(void) {
int numbers[9][9];
int i = 0;
int count;
int j = 0;
FILE *file;
file = fopen("numbers.txt", "r");
for (count = 1; count < 101; count++) {
fscanf(file, "%d", &numbers[i][j]);
j++;
if ((count != 1) && (count % 10 == 0)) {
i++;
j = 0;
}
}
fclose(file);
int p = 0;
int q = 0;
for (p = 0; p < NR; p++) {
for (q = 0; q < NC; q++) {
printf("%d", numbers[p][q]);
}
printf("\n");
}
return 0;
}
As SparKot noted in a comment, to read a 10x10 matrix, you need to define the matrix with 10x10 elements:
int numbers[10][10];
That has to be one of the weirder ways of reading a 10x10 matrix that I've ever seen. Why not go for a simple approach of nested loops. Since the data contains floating-point numbers, you need to read them as double (or perhaps float) values.
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
double double_val;
if (fscanf(file, "%lf", &double_val) != 1)
{
fprintf(stderr, "failed to read matrix[i][j]\n", i, j);
exit(EXIT_FAILURE);
}
numbers[i][j] = double_val;
}
}
The mess with double_val works around the data containing floating point numbers and your original code trying to read integers. You'll get one valid value; thereafter, fscanf() will return 0 because the . is not a part of a valid integer. This highlights the importance of checking the return value from fscanf() and its relatives.
Frankly, you should be using double numbers[10][10]; for the data from the file. Then you could read directly into the array:
if (fscanf("%lf", &numbers[i][j]) != 1)
But you'd need to check (and probably change) all the rest of the code too.
There are multiple issues in your code:
the matrix is too small, make it numbers[NR][NC].
you do not check for fopen failure: you will have undefined behavior if the file numbers.txt is not in the current directory or cannot be open for reading.
you read the file contents as integers, but the file contains floating point numbers with a . decimal separator: the second and subsequent fscanf() will get stuck on the . and keep returning 0 without modifying the destination number, leaving the matrix mostly uninitialized. Make the matrix double numbers[NR][NC], read the numbers with %lf and test for conversion failure.
the counting method in the reading loop is weird. Just use 2 nested for loops with proper counter and tests.
printing the matrix contents, you should output at least a space between numbers so the output is readable.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define NR 10
#define NC 10
int main() {
double numbers[NR][NC];
FILE *file;
file = fopen("numbers.txt", "r");
if (file == NULL) {
fprintf(stderr, "cannot open numbers.txt: %s\n", strerror(errno));
return 1;
}
for (int i = 0; i < NR; i++) {
for (int j = 0; j < NC; j++) {
if (fscanf(file, "%lf", &numbers[i][j]) != 1) {
fprintf(stderr, "error reading number at row %d, col %d\n",
i + 1, j + 1);
fclose(file);
return 1;
}
}
}
fclose(file);
for (int p = 0; p < NR; p++) {
for (int q = 0; q < NC; q++) {
printf(" %5g", numbers[p][q]);
}
printf("\n");
}
return 0;
}
Clear all a common condition that causes programs to crash; they are often associated with a file named core.
code is showing segmentation fault.

Sorting Words and Numbers from a file in C

I have been tasked with writing a function that takes a string reference and an integer reference parameter. The function must scan a .txt file and set the reference parameters to the name of the player with the highest score and the corresponding score.
This is written in the scores.txt file I must reference:
Ronaldo
10400
Didier
9800
Pele
12300
kaka
8400
Cristiano
8000
I currently have this much coding wrote however I am stuck as to how I am suppose to match the names up with the score since they have to be in no particular order. Within my coding I sort the numbers from greatest to least but I am not sure if this is needed or not.
FILE *input;
char name[name_len];
double score[score_len];
int a;
int b;
double placeholder;
input = fopen("scores.txt", "r");
if (input == NULL)
{
printf("\n Cannot open scores.txt for input\n");
}
for (a =0; a < 5; ++a)
fscanf(input, "%s%lf", name, score);
for (a = 0; a < 5; ++a) /* Repeats the step until three numbers are sorted*/
{
for (b = a + 1; b < 5; ++b) /* Repeats until the last two numbers are sorted*/
{
if (score[a] < score[b]) /* Sorts the 3 numbers using a placeholder to exchange the numbers in the array*/
{
placeholder = score[a];
score[a] = score[b];
score[b] = placeholder;
}
}
}
fclose(input);
return 0;
Any help regarding the solution or how I can move forward is much appreciated.
You can just read the number and name in, and replace the value of the score and the name if its bigger.
char name[name_len];
double score[score_len];
char highScoreName[name_len];
double highScore = 0;
...
for (int a = 0; a < 5; ++a)
{
fscanf(input, "%s %lf", name, score[a]);
if (highScore < score[a])
{
highScore = score[a];
strcpy(highScoreName, name);
}
}

Why does my conversion method in C continue to fail?

I am trying to convert from a popen pass, to a float as the final result. I have tried converting to a char, and then into a float in every possible way I can find, however the output I have seen using printf seems to be wrong every time. I have tried using a tostring function, as well as using a %s like in the printf function that returns the correct function, however it all seems to give me the wrong output as soon as I try to convert the output. Should I be trying a different conversion method?
Here is the code.
FILE * uname;
char os[80];
int lastchar;
char n;
uname = popen("sudo python ./return63.py", "r");
lastchar = fread(os, 1, 80, uname);
os[lastchar] = "\0";
n = toString(("%s", os));
printf("THE DIRECT OUTPUT FROM PY IS %s", os);
printf("THE DIRECT OUTPUT For n IS %c", n);
float ia = n - 0;
long p = ia - 0;
float dd = p - 0;
printf("Your OS is %f", dd);
Output from the PY is 'THE DIRECT OUTPUT FROM PY IS 63.0' , which is the correct value,
output from the n is 'THE DIRECT OUTPUT For n IS �'
output from the dd is 'Your OS is Your OS is 236.000000'
The function tostring was pulled from an answered question about how to get the output from another answered question. I have tried with and without this code.
int toString(char a[]) {
int c, sign, offset, n;
if (a[0] == '-') { // Handle negative integers
sign = -1;
}
if (sign == -1) { // Set starting position to convert
offset = 1;
}
else {
offset = 0;
}
n = 0;
for (c = offset; a[c] != '\0'; c++) {
n = n * 10 + a[c] - '0';
}
if (sign == -1) {
n = -n;
}
return n;
}
toString returns an int, so store an int and output an int.
int n = toString(os); // Also removed the obfuscating '("%s", ..)'
printf("THE DIRECT OUTPUT For n IS %d", n);
Also your toString function has undefined behavior because sign might be read without being initialized.
if (a[0] == '-') { // Handle negative integers
sign = -1;
offset = 1;
}
else {
sign = 1;
offset = 0;
}
You have a potential os buffer overflow and you are not doing the null termination of os correctly:
lastchar = fread(os, 1, sizeof(os) - 1, uname); // Only read one byte less
os[lastchar] = '\0'; // changed from string "\0" to char '\0'
And finally you are not checking the input string for digits, you are accepting every input (also the '.' in "63.0"). You might want to stop at the first non-digit character:
for (c = offset; !isdigit((unsigned char)a[c]); c++) {

How to save the data which i read in an array from a file in C

So while doing this assignment i encountered a problem where i tried to save some set of values(float) in an Array so that i can use them later on producing a graph, but the problem which i face here is that i read the values and i can print them but later which i checked the array the numbers which were stored there were not the same.
Im trying to save in in avg[].
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
float maximum(float array[])
{
float max=0;
for(int i=0;i<100;i++)
{
if (array[i]>max)
max=array[i];
}
return max;
}
float minimum(float array[])
{
float min=0;
for(int i=0;i<100;i++)
{
if (array[i]<min)
min=array[i];
}
return min;
}
char * read(char *filename)
{
FILE * sample;
sample = fopen(filename,"r"); //like file open in notepad ,which file? and what to do?
int count = 0;
static char singleline[100];
int cnt = 0;
int sum = 0;
int oldyear = -1;
float avg[82];
while(!feof(sample)) //read that until end.
{
count++;
fgets(singleline,150,sample);
if (count>21 && singleline[33]!='9')
{
char y[5], t[6];
for (int i = 14; i < 18; i++)
{
y[i - 14] = singleline[i];
}
y[4]='\0';
for (int i= 24;i <29;i++)
{
t[i-24]=singleline[i];
}
t[5]='\0';
int year = atoi(y);
int temp = atoi(t);
//printf("year : %i ,temp: %i\n",year, temp);
if (year == oldyear)
{
cnt++;
sum += temp;
}
else
{
int l=0;
l++;
avg[l] = 0.1 * sum / cnt;
if (cnt != 0)
{
printf("Fuer %i - %i Werte - Durchschnitt %.2f °C\n", oldyear, cnt, avg[l]);
cnt = 1;
sum = temp;
//save[l]=avg;
}
oldyear = year;
}
}
}
float last = 0.1 * sum / cnt;
printf("Fuer %i - %i Werte - Durchschnitt %.2f °C\n", oldyear, cnt-1, last);
fclose(sample);
//for(int i=0;i<)
for(int i=0;i<125;i++)
{
printf("%f\n",avg[i]);
}
printf("\nMax Temp= %f",maximum(avg));
printf("\nMax Temp= %f",minimum(avg));
return singleline;
}
int main()
{
char * file1 = "TG_STAID000476.txt";
read(file1);
//char * file2 = "TG_STAID000179.txt";
//read(file2);
return 0;
}
So yea, the problem was to read the year and the corresponding values and form an Average value for that particular year and then represent it in a graph.
I can do the first part where it takes the Average, but when i tried using it later,it had wrong values stored in it, you can see that where i tried to print all the values of avg[], can anyne please help me figure out how to correct the mistake, i want them to be saved as float.
The assignment datasheet is here. https://www.scribd.com/document/333844245/TG-STAID000179
I tried reading the values and used atoi to save them, and then used them to get the Average, i used Count>21 because the text before them are not required and when it reads a '9' on 34th column,it ignores since its not a valid data(in data sheet)
The variable l, intended to count the computed year temperature averages, is defined and initialized in the block where a year change is handled, thus always reset to zero. Correct this by moving the definition outside of the line read loop, perhaps even at global scope (see 2.).
The maximum() and minimum() functions operate on array elements 0 to 99, irrespective of the fact that the passed argument is defined as avg[82] and some elements at the end are not initialized. Correct this by using the actual number l of stored elements, either as a global scope variable or an additional function argument.
The singleline buffer is too short and thus overflows.
The while(!feof(sample)) loop cycles one extra time after the last line has been read, because EOF is not recognized before the next fgets(). Correct this by using the return value of fgets() to test EOF.
avg[l] = 0.1 * sum / cnt is evaluated even if cnt is zero. Correct this by moving this expression inside the if (cnt != 0) { … } block, also the l++, but behind the printf().
cnt = 1 is not executed if cnt is zero. This causes the very first data point to not be counted. Correct this by moving this expression behind the if (cnt != 0) { … } block.
The extra loop cycle (cf. 4.) may have led to use cnt-1 in the final printf("Fuer %i - %i Werte - Durchschnitt %.2f °C\n", oldyear, cnt-1, last);, but correct is just cnt.
The loop for(int i=0;i<125;i++) should also use the actual number l of stored elements, not 125.
To be noted is that the final year's average is (maybe intentionally) not stored in avg[].

Resources