Reputation: 61
I'm trying to read a file that contains a sequence of numbers
Example:
43917778700000762841090006653470575088202000
43919478100000762851090006653540575088203000
43919765400000815661090006653620575088204000
My code:
typedef struct rArc{
long long int code;
}data;
int main(){
long long int code,i=0;
FILE *arc;
data *v;
v = NULL;
arc = fopen("CODES.txt","r");
while(fscanf(arc,"%lld",&code) != EOF){
v = (data *)realloc(v,sizeof(data) * (i + 1));
v[i].code = code;
i++;
}
for(int j=0;j<i;j++){
printf("%lld\n",v[j].code);
}
}
But because the number is too big, it outputs some wierd random numbers. I was thinking in taking the last digit with modulo and adding into a vector, but because I cant even read it there's no way to do it the way i'm trying
Update
I've managed to read the file by changing the struct and main code variables to char code[45], I'm still working on how to do the maths but it was a start i guess
while(fscanf(arc,"%45s\n",&code) != EOF){
v = (data *)realloc(v,sizeof(data) * (i + 1));
v[i].code = code;
i++;
}
for(int j=0;j<i;j++){
printf("%45s\n",v[j].code);
}
}
Upvotes: 2
Views: 145
Reputation: 84642
Even after 3 iterations of clarification in the comments, I'm still not entirely clear on your algorithm, but I believe I understand it enough to help. From your responses to my comments, I understand you want to replace text at the 10th, 21st & 32nd
characters with values arrived at by:
summing all characters to the left of the position,
the sum is produced by multiplying every other character by 2
starting by multiplying the 1st character by 2
, the second by 1
, the third by 2
and continuing with the 1-2-1-2-1...
pattern of multiplying each digit until the wanted index is reached, and finally
if any multiple by 2
exceeds 10
, then you increase the sum by the product modulo 10
(e.g. sum = sum + (digit * 2-1-multiple) % 10
) (or you may want to mod to total accumulated sum by 10
before each replacement at the 10th, 21st and 32nd characters -- that part is still unclear)
That being so, you can approach the problem by reading each string of digits into a fixed buffer. (do not skimp on buffer size). Once the line is read, iterate over the characters (validating each is a digit) keeping a running sum according to the pattern above until you reach the desired index. At the required index, replace the characters in the original string with the sum at that point, and continue until the final index and replacement at the 32nd character has been made.
To do that you can start by declaring your buffer to hold the file and opening the file (and validating it is open). You can take the filename to open as the 1st argument to your program or read from stdin
if no argument is provided, e.g.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAXC 512 /* constant for line-buffer size */
int main (int argc, char **argv) {
char buf[MAXC] = ""; /* buffer to read each line */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
Next you will want to begin your read loop and declare the variables required to locate the desired positions to insert the sums, a way to keep track of your 2-1-2-1...
multiplier sequence and your running sum. While not required here (you will only access through the 32nd character, it is a good idea to trim the trailing '\n'
included in your buffer by fgets
(or POSIX getline
) as part of your validation that all characters fit in your buffer, e.g.
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
int const pos[] = { 10, 21, 32 }, /* indexes to replace */
npos = sizeof pos / sizeof *pos; /* no. of indexes */
int ndx = 0, /* buffer index */
*pdx = (int *)pos, /* pointer to pos */
mult = 2; /* 2-1-2-... multiplier */
size_t len = strlen (buf); /* length of string */
unsigned sum = 0; /* sum of digits */
if (len && buf[len - 1] == '\n') /* check for trailing '\n' */
buf[--len] = 0; /* overwrite with nul-character */
else if (len == MAXC - 1) { /* otherwise string too long */
fprintf (stderr, "error: line too long.\n");
return 1;
}
printf ("original: %s\n", buf); /* output the original string */
Once you have read your line and validated it fit, etc.. you need to loop over each character in the string performing your sum increment and replacement where required. You should also validate that each character read is a digit and not some stray alpha-character, or otherwise. By using a simple preprocessor #define
passed as part of your compile string, you can provide optional debug output to help you sort out any problems with your algorithm, e.g.
for (; buf[ndx]; ndx++) { /* iterate over each character */
if (!isdigit (buf[ndx])) { /* validate character is digit */
fprintf (stderr, "error: non-digit '%c'.\n", buf[ndx]);
return 1;
}
sum += ((buf[ndx] - '0') * mult) % 10; /* increment sum by % 10 */
if (ndx + 1 == *pdx) { /* check if ndx+1 is position */
int ndigit = 0; /* no. of digits in sum */
char tmp[MAXC] = ""; /* tmp buffer for sum as string */
ndigit = sprintf (tmp, "%u", sum); /* write sum to tmp */
#ifdef DEBUG /* debug output */
printf ("ndx+1: %2d, sum: %3u, ndigits: %d\n",
ndx+1, sum, ndigit);
#endif
if (ndigit) /* validate characters written to tmp */
memcpy (&buf[ndx], tmp, ndigit); /* copy to buf */
pdx++; /* increment pos array index */
if (*pdx == npos) /* check if past last pos index */
break;
}
mult = (mult & 1) ? 2 : 1; /* toggle mult 2-1-2-1... */
}
printf ("revised : %s\n\n", buf); /* output updated number in buf */
}
Putting it altogether, and adding the close of open file, you could do something like the following:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAXC 512 /* constant for line-buffer size */
int main (int argc, char **argv) {
char buf[MAXC] = ""; /* buffer to read each line */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
int const pos[] = { 10, 21, 32 }, /* indexes to replace */
npos = sizeof pos / sizeof *pos; /* no. of indexes */
int ndx = 0, /* buffer index */
*pdx = (int *)pos, /* pointer to pos */
mult = 2; /* 2-1-2-... multiplier */
size_t len = strlen (buf); /* length of string */
unsigned sum = 0; /* sum of digits */
if (len && buf[len - 1] == '\n') /* check for trailing '\n' */
buf[--len] = 0; /* overwrite with nul-character */
else if (len == MAXC - 1) { /* otherwise string too long */
fprintf (stderr, "error: line too long.\n");
return 1;
}
printf ("original: %s\n", buf); /* output the original string */
for (; buf[ndx]; ndx++) { /* iterate over each character */
if (!isdigit (buf[ndx])) { /* validate character is digit */
fprintf (stderr, "error: non-digit '%c'.\n", buf[ndx]);
return 1;
}
sum += ((buf[ndx] - '0') * mult) % 10; /* increment sum by % 10 */
if (ndx + 1 == *pdx) { /* check if ndx+1 is position */
int ndigit = 0; /* no. of digits in sum */
char tmp[MAXC] = ""; /* tmp buffer for sum as string */
ndigit = sprintf (tmp, "%u", sum); /* write sum to tmp */
#ifdef DEBUG /* debug output */
printf ("ndx+1: %2d, sum: %3u, ndigits: %d\n",
ndx+1, sum, ndigit);
#endif
if (ndigit) /* validate characters written to tmp */
memcpy (&buf[ndx], tmp, ndigit); /* copy to buf */
pdx++; /* increment pos array index */
if (*pdx == npos) /* check if past last pos index */
break;
}
mult = (mult & 1) ? 2 : 1; /* toggle mult 2-1-2-1... */
}
printf ("revised : %s\n\n", buf); /* output updated number in buf */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
return 0;
}
(note: the algorithm above includes the replaced values as part of the sum
used at the next replacement index. i.e. your replacement at the 10th character is 52
for the first line. The digits 5
and 2
are used as part of the sum
inserted at the 21st character)
Compile With DEBUG Defined (-DDEBUG)
$ gcc -Wall -Wextra -pedantic -std=c11 -Ofast -DDEBUG \
-o bin/str_fill_sum_dbg str_fill_sum.c
(note: the '\'
line-continuation is used above simply to keep the compile string from scrolling beyond the right margin of the web-page here. Also, I put all compiled executables in a bin
subdirectory to keep my source directory clean, you can omit the bin/
portion of the executable name)
Example DEBUG Use/Output
The debug output shows the index, the current sum at that index which is inserted, and the number of characters replaced:
$ ./bin/str_fill_sum_dbg <dat/sumdigits.txt
original: 34194716400003108771090006638210572088201000
ndx+1: 10, sum: 52, ndigits: 2
ndx+1: 21, sum: 79, ndigits: 2
ndx+1: 32, sum: 109, ndigits: 3
revised : 34194716452003108771790006638211092088201000
original: 34193716400000921121090006638390572088201000
ndx+1: 10, sum: 50, ndigits: 2
ndx+1: 21, sum: 68, ndigits: 2
ndx+1: 32, sum: 104, ndigits: 3
revised : 34193716450000921121680006638391042088201000
original: 34191718400000607281090006638470572088201000
ndx+1: 10, sum: 48, ndigits: 2
ndx+1: 21, sum: 69, ndigits: 2
ndx+1: 32, sum: 103, ndigits: 3
revised : 34191718448000607281690006638471032088201000
original: 34195718400000550361090006638540572088201000
ndx+1: 10, sum: 46, ndigits: 2
ndx+1: 21, sum: 59, ndigits: 2
ndx+1: 32, sum: 98, ndigits: 2
revised : 34195718446000550361590006638549872088201000
original: 34192719900000550361090006638620572088201000
ndx+1: 10, sum: 51, ndigits: 2
ndx+1: 21, sum: 64, ndigits: 2
ndx+1: 32, sum: 95, ndigits: 2
revised : 34192719951000550361640006638629572088201000
original: 34198721400000550361090006638700572088201000
ndx+1: 10, sum: 47, ndigits: 2
ndx+1: 21, sum: 62, ndigits: 2
ndx+1: 32, sum: 88, ndigits: 2
revised : 34198721447000550361620006638708872088201000
Compile Normally
Simply drop the definition of the DEBUG
define to omit the debug output, and out the executable in a separate filename if you like so both are available:
$ gcc -Wall -Wextra -pedantic -std=c11 -Ofast \
-o bin/str_fill_sum str_fill_sum.c
Example Use/Output
$ ./bin/str_fill_sum <dat/sumdigits.txt
original: 34194716400003108771090006638210572088201000
revised : 34194716452003108771790006638211092088201000
original: 34193716400000921121090006638390572088201000
revised : 34193716450000921121680006638391042088201000
original: 34191718400000607281090006638470572088201000
revised : 34191718448000607281690006638471032088201000
original: 34195718400000550361090006638540572088201000
revised : 34195718446000550361590006638549872088201000
original: 34192719900000550361090006638620572088201000
revised : 34192719951000550361640006638629572088201000
original: 34198721400000550361090006638700572088201000
revised : 34198721447000550361620006638708872088201000
Look things over and let me know if you have further questions. If you algorithm is different than shown above, you should be able to easily incorporate any needed changes.
If modulo
Of Total Before Insertion
If instead of taking modulo 10
of the result of each digit multiplied by 2
, you instead want to just take the modulo of the sum before insertion, you could replace your character iteration loop with the following:
for (; buf[ndx]; ndx++) { /* iterate over each character */
if (!isdigit (buf[ndx])) { /* validate character is digit */
fprintf (stderr, "error: non-digit '%c'.\n", buf[ndx]);
return 1;
}
sum += ((buf[ndx] - '0') * mult); /* increment by digit*mult */
if (ndx + 1 == *pdx) { /* check if ndx+1 is position */
int replace = sum % 10;
#ifdef DEBUG /* debug output */
printf ("ndx+1: %2d, sum: %3u, replace: %d\n",
ndx+1, sum, replace);
#endif
buf[ndx] = replace + '0'; /* replace char at buf[ndx] */
pdx++; /* increment pos array index */
if (*pdx == npos) /* check if past last pos index */
break;
}
mult = (mult & 1) ? 2 : 1; /* toggle mult 2-1-2-1... */
}
Example DEBUG Use/Output
In that case the replacements of a single character would be as follows:
$ ./bin/str_fill_sum_dbg2 <dat/sumdigits.txt
original: 34194716400003108771090006638210572088201000
ndx+1: 10, sum: 52, replace: 2
ndx+1: 21, sum: 95, replace: 5
ndx+1: 32, sum: 145, replace: 5
revised : 34194716420003108771590006638215572088201000
original: 34193716400000921121090006638390572088201000
ndx+1: 10, sum: 50, replace: 0
ndx+1: 21, sum: 78, replace: 8
ndx+1: 32, sum: 145, replace: 5
revised : 34193716400000921121890006638395572088201000
original: 34191718400000607281090006638470572088201000
ndx+1: 10, sum: 48, replace: 8
ndx+1: 21, sum: 93, replace: 3
ndx+1: 32, sum: 157, replace: 7
revised : 34191718480000607281390006638477572088201000
original: 34195718400000550361090006638540572088201000
ndx+1: 10, sum: 56, replace: 6
ndx+1: 21, sum: 87, replace: 7
ndx+1: 32, sum: 146, replace: 6
revised : 34195718460000550361790006638546572088201000
original: 34192719900000550361090006638620572088201000
ndx+1: 10, sum: 61, replace: 1
ndx+1: 21, sum: 92, replace: 2
ndx+1: 32, sum: 148, replace: 8
revised : 34192719910000550361290006638628572088201000
original: 34198721400000550361090006638700572088201000
ndx+1: 10, sum: 57, replace: 7
ndx+1: 21, sum: 88, replace: 8
ndx+1: 32, sum: 141, replace: 1
revised : 34198721470000550361890006638701572088201000
Upvotes: 1
Reputation: 1
//This Program will solve your problem. If you have any doubt ask me
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int sum10th = 0 , sum21st = 0 , sum32nd = 0; //to store the sum of 10th 21st 32nd
FILE *stream;
char *line = NULL;
size_t len = 0;
ssize_t nread;
stream = fopen("number.txt","r");
while ((nread = getline(&line, &len, stream)) != -1)
{
if( nread >= 10)
{
sum10th += line[10 - 1] - 48 ;
if( nread >= 21)
{
sum21st += line[21 - 1] - 48;
if( nread >= 32)
sum32nd += line[32 - 1] - 48;
}
}
strcpy(line," "); //empty line
}
free(line);
fclose(stream);
printf("Sum at 10th 21st 32th is %d %d %d\n",sum10th , sum21st, sum32nd);
return 0;
}
/*
number.txt
46546546546548614684654654651666
65465455546868464654684797987987
46865465465465465465654686468468
*/
/*
ouput
Sum at 10th 21st 32th is 14 18 21
*/
Upvotes: 0