Large numbers, sums, and data conversions - c

I've been pouring over my code (which does not work) now for quite some time. It is for a Project Euler problem in which one is given a very large sum to find, and then required to print the first ten digits of said sum. (The problem can be found here: https://projecteuler.net/problem=13)
I have run several 'tests' where I add print commands to see various values at various points in the code. When I run the code, I have gotten anything from symbols to ten digit numbers that should be single digits.
Anyways. My question is this: is this a type conversion issue or is there some other glaring issue with my method that I'm missing? I've been studying type conversions trying to find a fix, but to no avail.
Thank you for any help!
The code is as follows:
// this is a program to find a very large sum of many very large numbers
#include <stdio.h>
#include <math.h>
int main()
{
//declare all ints needed
int i;
int j;
int d; // digit, need to add 48
int placesum; // sum of addition in _'s place (1's, 10's, 10000's)
int place; // final place value
int c = 0, tens = 1, otherc; // counters for start finder
int a = 0; // another counter
//declare all arrays
char numarray[101][51]; //array of strings containing all 100 numbers
char sum[100];
printf("please save data to largesumdata.txt\n\n press enter when ready");
getchar();
// THE PROBLEM- I don't know how to get my data into my program // FIXED
// using fscanf()
FILE *pf; // declare a pointer to the file
pf = fopen("largesumdata.txt", "r"); // trys to open file // "r" means read only
if(pf == NULL)
printf("Unable to open file, sorry Jar\n");
else
{
for(j = 0; j < 100; j++)
fscanf(pf, "%s\n", &numarray[j]); // fscanf(pointer, data type, location)
}
//TESTING
//printf("You have reached point A\n");//POINT A WAS REACHED
//TESTING
//TESTING
//printf("Check1, %c\n", numarray[45][23]);
//TESTING
//TESTING
//printf("%c\n", numarray[90][22]);//Can successfully call characters from array
//TESTING
// (Brute force attempt) //I NEVER MESS WITH numarray WHY IS IT CHANGING
for(i = 49; i >= 0; i--)
{
//printf("%d\n", d);
for(j = 0; j < 100; j++)
{
d = (int)numarray[j][i] - 'o';
//printf("%d\n", d);
//holdup// d -= 48; // ASCII conversion // could also write "d = d-48"
//printf("%d\n", d);
placesum += d; // could also write "placesum = placesum + d"
//printf("%d\n", placesum);
}
place = placesum % 10;
placesum = placesum / 10; // takes "10's place" digit for next column
// now need to put 'int place' into 'char sum'
sum[i+5] = (char)place+'0'; // ASCII conversion // "+5" for extra space //HERE not properly stored in sum
}
//TESTING
//printf("Check2, %c\n", numarray[45][23]);
//TESTING
//TESTING
//printf("You have reached point B\n");//POINT B WAS REACHED
//TESTING
// find out where sum starts
for(c=0; c<10; c++)
if(sum[c] != '0')
break;
//TESTING
//printf("You have reached point C\n"); //POINT C WAS REACHED
//TESTING
otherc = 4-c;
printf("The first 10 digits of the sum of all those f***ing numbers is....\n");
printf("%d-%d-%d-%d-%d-%d-%d-%d-%d-%d", sum[otherc, otherc+1, otherc+2, otherc+3, otherc+4, otherc+5, otherc+6, otherc+7, otherc+8, otherc+9]);
//%c-%c-%c-%c-%c-%c-%c-%c-%c-%c //copy and paste purposes
//%d-%d-%d-%d-%d-%d-%d-%d-%d-%d // ^^^^^
getchar();
return 0;
}
P.S. I apologize if my plethora of notes is confusing

You are using wrong form to print an array in C.
sum[otherc, otherc+1, otherc+2, otherc+3, otherc+4, otherc+5, otherc+6, otherc+7, otherc+8, otherc+9] -> This actually decays to sum[otherc+9] because C treats , as an operator.
To print value at each array index, you should use it like this: sum[otherc], sum[otherc+1], sum[otherc+2],..
To read more about C's , (comma) operator, you can begin here
In your printf as I explained above, the first format specifier %d gets sum[otherc + 9], since sum[otherc,...,otherc+9] is actually a single number and that is otherc + 9th index of array sum. You do not provide anything to print for other format specifiers, hence you get garbage.

After a while I revisited my code, and realized that I was working with numbers upwards of 10 million. I had a mix of int, long int, and long long int variables declared.
I re-analyzed which was which, and made sure that all variables could handle the data it needed to (after looking at this handy link, showing what max integer sizes are for different data types.
Before I had been using the wrong ones, and going over the max values returned incorrect values, causing my program to crash during run time.
Lesson here: Check your data types!

Related

How to find the total number of a certain element in an array(C)

I'm trying to create a complete C program to read ten alphabets and display them on the screen. I shall also have to find the number of a certain element and print it on the screen.
#include <stdio.h>
#include <conio.h>
void listAlpha( char ch)
{
printf(" %c", ch);
}
int readAlpha(){
char arr[10];
int count = 1, iterator = 0;
for(int iterator=0; iterator<10; iterator++){
printf("\nAlphabet %d:", count);
scanf(" %c", &arr[iterator]);
count++;
}
printf("-----------------------------------------");
printf("List of alphabets: ");
for (int x=0; x<10; x++)
{
/* I’m passing each element one by one using subscript*/
listAlpha(arr[x]);
}
printf("%c",arr);
return 0;
}
int findTotal(){
}
int main(){
readAlpha();
}
The code should be added in the findTotal() element. The output is expected as below.
Output:
List of alphabets : C C C A B C B A C C //I've worked out this part.
Total alphabet A: 2
Total alphabet B: 2
Total alphabet C: 6
Alphabet with highest hit is C
I use an array to count the number of the existence of each character,
I did this code but the display of number of each character is repeated in the loop
int main()
{
char arr[100];
printf("Give a text :");
gets(arr);
int k=strlen(arr);
for(int iterator=0; iterator<k; iterator++)
{
printf("[%c]",arr[iterator]);
}
int T[k];
for(int i=0;i<k;i++)
{
T[i]=arr[i];
}
int cpt1=0;
char d;
for(int i=0;i<k;i++)
{int cpt=0;
for(int j=0;j<k;j++)
{
if(T[i]==T[j])
{
cpt++;
}
}
if(cpt>cpt1)
{
cpt1=cpt;
d=T[i];
}
printf("\nTotal alphabet %c : %d \n",T[i],cpt);
}
printf("\nAlphabet with highest hit is : %c\n",d,cpt1);
}
There is no way to get the number of elements You write in an array.
Array in C is just a space in the memory.
C does not know what elements are actual data.
But there are common ways to solve this problem in C:
as mentioned above, create an array with one extra element and, fill the element after the last actual element with zero ('\0'). Zero means the end of the actual data. It is right if you do not wish to use '\0' among characters to be processed. It is similar to null-terminated strings in C.
add the variable to store the number of elements in an array. It is similar to Pascal-strings.
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE 10
char array[ARRAY_SIZE + 1];
int array_len(char * inp_arr) {
int ret_val = 0;
while (inp_arr[ret_val] != '\0')
++ret_val;
return ret_val;
}
float array_with_level[ARRAY_SIZE];
int array_with_level_level;
int main() {
array[0] = '\0';
memcpy(array, "hello!\0", 7); // 7'th element is 0
printf("array with 0 at the end\n");
printf("%s, length is %d\n", array, array_len(array));
array_with_level_level = 0;
const int fill_level = 5;
int iter;
for (iter = 0; iter < fill_level; ++iter) {
array_with_level[iter] = iter*iter/2.0;
}
array_with_level_level = iter;
printf("array with length in the dedicated variable\n");
for (int i1 = 0; i1 < array_with_level_level; ++i1)
printf("%02d:%02.2f ", i1, array_with_level[i1]);
printf(", length is %d", array_with_level_level);
return 0;
}
<conio.h> is a non-standard header. I assume you're using Turbo C/C++ because it's part of your course. Turbo C/C++ is a terrible implementation (in 2020) and the only known reason to use it is because your lecturer made you!
However everything you actually use here is standard. I believe you can remove it.
printf("%c",arr); doesn't make sense. arr will be passed as a pointer (to the first character in the array) but %c expects a character value. I'm not sure what you want that line to do but it doesn't look useful - you've listed the array in the for-loop.
I suggest you remove it. If you do don't worry about a \0. You only need that if you want to treat arr as a string but in the code you're handling it quite validly as an array of 10 characters without calling any functions that expect a string. That's when it needs to contain a 0 terminator.
Also add return 0; to the end of main(). It means 'execution successful' and is required to be conformant.
With those 3 changes an input of ABCDEFGHIJ produces:
Alphabet 1:
Alphabet 2:
Alphabet 3:
Alphabet 4:
Alphabet 5:
Alphabet 6:
Alphabet 7:
Alphabet 8:
Alphabet 9:
Alphabet 10:-----------------------------------------List of alphabets: A B C D E F G H I J
It's not pretty but that's what you asked for and it at least shows you've successfully read in the letters. You may want to tidy it up...
Remove printf("\nAlphabet %d:", count); and insert printf("\nAlphabet %d: %c", count,arr[iterator]); after scanf(" %c", &arr[iterator]);.
Put a newline before and after the line of minus signs (printf("\n-----------------------------------------\n"); and it looks better to me.
But that's just cosmetics. It's up to you.
There's a number of ways to find the most frequent character. But at this level I recommend a simple nested loop.
Here's a function that finds the most common character (rather than the count of the most common character) and if there's a tie (two characters with the same count) it returns the one that appears first.
char findCommonest(const char* arr){
char commonest='#'; //Arbitrary Bad value!
int high_count=0;
for(int ch=0;ch<10;++ch){
const char counting=arr[ch];
int count=0;
for(int c=0;c<10;++c){
if(arr[c]==counting){
++count;
}
}
if(count>high_count){
high_count=count;
commonest=counting;
}
}
return commonest;
}
It's not very efficient and you might like to put some printfs in to see why!
But I think it's at your level of expertise to understand. Eventually.
Here's a version that unit-tests that function. Never write code without a unit test battery of some kind. It might look like chore but it'll help debug your code.
https://ideone.com/DVy7Cn
Footnote: I've made minimal changes to your code. There's comments with some good advice that you shouldn't hardcode the array size as 10 and certainly not litter the code with that value (e.g. #define ALPHABET_LIST_SIZE (10) at the top).
I have used const but that may be something you haven't yet met. If you don't understand it and don't want to learn it, remove it.
The terms of your course will forbid plagiarism. You may not cut and paste my code into yours. You are obliged to understand the ideas and implement it yourself. My code is very inefficient. You might want to do something about that!
The only run-time problem I see in your code is this statement:
printf("%c",arr);
Is wrong. At this point in your program, arr is an array of char, not a single char as expected by the format specifier %c. For this to work, the printf() needs to be expanded to:
printf("%c%c%c%c%c%c%c%c%c%c\n",
arr[0],arr[1],arr[2],arr[3],arr[4],
arr[5],arr[6],arr[7],arr[8],arr[9]);
Or: treat arr as a string rather than just a char array. Declare arr as `char arr[11] = {0};//extra space for null termination
printf("%s\n", arr);//to print the string
Regarding this part of your stated objective:
"I shall also have to find the number of a certain element and print it on the screen. I'm new to this. Please help me out."
The steps below are offered to modify the following work
int findTotal(){
}
Change prototype to:
int FindTotal(char *arr);
count each occurrence of unique element in array (How to reference)
Adapt above reference to use printf and formatting to match your stated output. (How to reference)

Performing a sum between two arrays of digis

Had an interview today and I was asked the following question - given two arrays arr1 and arr2 of chars where they contain only numbers and one dot and also given a value m, sum them into one array of chars where they contain m digits after the dot. The program should be written in C. The algorithm was not important for them, they just gave me a compiler and 20 minutes to pass their tests.
First of all I though to find the maximum length and iterate through the array from the end and sum the values while keeping the carry:
int length = (firstLength < secondLength) ? secondLength : firstLength;
char[length] result;
for (int i = length - 1; i >= 0; i--) {
// TODO: add code
}
The problem is that for some reason I'm not sure what is the right way to perform that sum while keeping with the dot. This loop should just perform the look and not counter to k. I mean that at this point I thought just adding the values and at the end i'll insert another loop which will print k values after the dot.
My question is how should look the first loop I mentioned (the one that actually sums), I'm really got stuck on it.
The algorithm was not important
Ok, I'll let libc do it for me in that case (obviously error handling is missing):
void sum(char *as, char *bs, char *out, int precision)
{
float a, b;
sscanf(as, "%f", &a);
sscanf(bs, "%f", &b);
a += b;
sprintf(out, "%.*f", precision, a);
}
It actually took me a lot longer than 20 mins to do this. The code is fairly long too so I don't plan on posting it here. In a nutshell, the code does:
normalize the 2 numbers into 2 new strings so they have the same number of decimal digits
allocate a new string with length of longer of the 2 strings above + 1
add the 2 strings together, 2 digits at a time, with carrier
it is not clear if the final answer needs to be rounded. If not, just expand/truncate the decimals to m digits. Remove any leading zero if needed.
I am not sure whether this is the best solution or not but here's a solution and I hope it helps.
#include<stdio.h>
#include<math.h>
double convertNumber(char *arr){
int i;
int flag_d=0; //To check whether we are reading digits before or after decimal
double a=0;
int j=1;
for(i=0;i<arr[i]!='\0';i++){
if(arr[i] !='.'){
if(flag_d==0)
a = a*10 + arr[i]-48;
else{
a = a + (arr[i]-48.0)/pow(10, j);
j++;
}
}else{
flag_d=1;
}
}
return a;
}
int main() {
char num1[] = "23.20";
char num2[] = "20.2";
printf("%.6lf", convertNumber(num1) + convertNumber(num2));
}

Why am I getting this output from printing the contents of an array with only 17 bytes?

I am working through CS50 on edX and have reached the problem where you have to do a checksum for credit card numbers.I am new to programming and even newer to C.
I am collecting the digits in arrays so I can manipulate them.
I have collected every other digit from the original number and multiplied this by two.
When I try to print this collection I get the digits I want initially but then a dash and whole load of other numbers - I have no idea where these are coming from?
// establishing another array to collect the doubled digits of every other digit from the first array
int doubledDigs[16];
int k = 0;
// building that array, ensuring to split any multi digit products and add them idnividually
for (int i = 0; i<= 15; i += 2, k++)
{
int a = collector[i] * 2;
if (a > 9)
{
for (int c=0; c < 2; c++, k++)
{
int b = a % 10;
doubledDigs[k] = b;
a = floor(a / 10);
}
}
doubledDigs[k] = a;
}
// print doubledDigs to check it is working
for (int i = 0; i <= 15; i++)
{
int b = doubledDigs[i];
printf ("%i", b);
}
printf ("\n");
//add all the doubled digits together
int doubledProduct = 0;
for (int i=0; i <= 15; i++)
{
doubledProduct += doubledDigs[i];
}
//print product to check
printf("%i\n", doubledProduct);
So if input 1234567890123 as my card number I get 62810410010620-74895702432659
-748924334
as an output.The first 14 digits are correct and the ones that I want - but where are all these other numbers coming from?
You're getting this output because of one of two things: either you're accessing your collector array out of its bounds, or you're failing to initialize the last few members of that array, resulting in garbage data being accessed.
Your algorithm assumes that collector and doubledDigs have the same number of members, but since your code doesn't include the part where you declare that array, it's unclear if that is true or not.
Assuming they are the same size, if you're filling collector with the input "1234567890123", then you're leaving 3 uninitialized members. In C, if you do not explicitly set the value of a variable or array member, its initial value is equal to whatever happens to be in memory at that particular location. For a signed int, that can be anywhere between 2,147,483,647 and -2,147,483,648.
To guard against this, the first thing you may want to do is zero-initialize your array using int collector[16] = {0};.
That only fixes things in the case that collector and doubledDigs are supposed to be the same size. If it's intended that collector has 14 members and doubledDigs has 16, for instance, you will have to revisit your loop logic. In that example, in the last 2 iterations of the loop, you will attempt access the 15th and 16th members of collector, which don't exist. C will not stop you from doing this, but the result is undefined behavior at best.

How do you read values from a text file and store them in 2 different arrays?

The text file contains 52 lines that are in the format:
A .013420
B .000191
C .011222
...
I want to ignore the letters and I need to extract the values from the file and store the first 26 in one array which I named freqOne[] and store the last 26 values in another array named freqTwo[]. I will later use these values for calculations.
here is my attempt:
#include <stdio.h>
#include <stdlib.h>
int main (){
FILE *input1;
/*char freqOne[26]; i use these arrays for attempt 1
char freqTwo[26];*/
double freqOne[26];
double freqTwo[26];
input1 = fopen("test8.txt", "r");
if(input1 == NULL){
perror("test8.txt");
exit(EXIT_FAILURE);
}
/* attempt one: all the values print out correctly but idk how to use them :(*/
/*while(fgets(freqOne, sizeof(freqOne), input1)){
printf("%s", freqOne);
}
while(fgets(freqTwo, sizeof(freqTwo), input1)){
printf("%s", freqTwo);
}
*/
/*fclose(input1); */
int h;
int i;
/* another attempt i made, this one prints out the a large negative number for every element :(*/
for(i=0; i<26; i++){
fscanf(input1,"%lf", &freqOne[i]);
printf("%lf\n", freqOne[i]);
}
for(h=0;h<26; h++){
fscanf(input1,"%lf", &freqTwo[h]);
printf("%lf\n", freqTwo[h]);
}
fclose(input1);
/*a = (freqOne[0]-freqTwo[0])*(freqOne[0]-freqTwo[0]);
printf("%lf", a);*/
}
In my first attempt, i was able to print out all the values correctly, but I am not sure how to use them. I printed them out as strings, but when I try to print them out as %lf, it gave me 0's for every value.
In my second attempt, I did some googling and found that I should try the fscanf function, but this did not work for either and a large negative number was printed out for every value. I am pretty stuck right now and out of ideas.
So OP can close this post:
To ignore the A,B,C, etc., use assignment suppression '*'
// fscanf(input1,"%lf", &freqOne[i]);
fscanf(input1,"%*s %lf", &freqOne[i]);
Always a good idea to check I/O function results:
if (fscanf(input1,"%*s %lf", &freqOne[i]) != 1) Handle_Unexpected_Input();

Why am I getting outputs of huge numbers with this program?

I am trying to make a program that allows the user to input a positive integer, and the program will output the sum of each digit added together. For example, if the user inputs 54, the program will output 9. For some reason, the program is outputting outrageously huge numbers. When 54 is the input, the output will read something like 5165451 or 2191235. I'm new to C programming, but I don't see a single thing wrong with this code..
//This program takes a positive integer
//from the user, and adds all the digits
//of the number together.
#include <stdio.h>
int main() {
system("clear");
int given, add, hold, i;
printf("Enter a positive integer (up to 10 digits): ");
scanf("%d", &given); //User input
for (i = 0; i < 10; i++) { //Loop to add digits
hold = (given % 10);
given = (given / 10);
add = (add + hold);
}
printf("Sum of the digits is %d\n", add); //Output
}
int given, add, hold, i;
You haven't initialized add, so it contains unspecified data, aka garbage. Using its value while it is unspecified is undefined behaviour.
Insert add = 0; before the loop to see if that helps.
I think the for loop is wrong
The loop will run 10 times whereas scanf will only take the input upto the limit of int data type i.e 32768.
You should make given a long data type.
and make the for loop as
for(;given!=0;)
{
hold = (given % 10);
given = (given / 10);
add = (add + hold);
}
and of course initialize add to zero.

Resources