How to increase the array block i want to manipulate - c

so my assignment is as follows:
"Write a program that reads in a list of numbers from an input text file called input.txt. For each number read, your program should determine and print out whether or not that number is abundant."
input.txt =
i have the code down and i think i finally figured out how to find and sum all the divisors to check if a number is abundant or not but the question i have is how do i go to the next array block to check the next number? Now it is checking "15" which is the first number to check(the 5 tells the program how many numbers it needs to check) but how do i get it to check the next number 3 and so on?
thank you!
#include <stdio.h>
#define SIZE 100
int main(){
FILE *ifp;
int cases;
int i;
int j;
int counter = 1;
int dividen =1;
int listArray[SIZE];
int sum = 0;
ifp = fopen("input.txt", "r");
fscanf(ifp,"%d", &cases);
for(i=0;i<cases;i++){
fscanf(ifp,"%d",&listArray[i]);
printf("%d\n", listArray[i]);}
while(listArray[0] > counter){
if(listArray[0] % dividen == 0){
sum = sum+dividen;
dividen++;
counter++;}
else{
dividen++;
counter++;}
}
if(listArray[0] > sum)
printf("\n%d is not an abundant number\n",listArray[0]);
system("pause");
return 0;
}

Move the code that checks abundance into the same loop where you store into listArray, or write another loop right after it that works on each element of listArray.
A good solution to problems like this in general is something like:
static const int TO_READ = 3; // For example.
FILE* file = open_input_file();
variable foo, bar, baz;
while ( TO_READ == fscanf( file, format, &foo, &bar, &baz )) {
do_stuff_with( foo, bar, baz );
}

Related

A function that inserts array into a binary file

My task is to write a function unesi_niz which allows the user to enter array of real numbers (maximum 100) where the entry ends with entering the number -1. The array that is entered in this way should be written to the binary file niz.bin as values of type double. The file must not contain anything other than members of the string (so it must not contain the entered number -1).
Then write a srednja_vrijednost function that calculates the mean value of the numbers in the niz.bin file and returns it. If the file does not exist or is empty, 0 should be returned.
So i started like this:
#include <stdio.h>
#include <stdlib.h>
#define vel 100
int i = 0;
int j = 0;
void unesi_niz() {
double pomocna;
double niz[100];
while (i != 100) {
scanf("%lf", &pomocna);
if (pomocna != -1) {
niz[i] = pomocna;
i++;
} else
break;
}
FILE *ulaz = fopen("niz.bin", "w");
if (!ulaz) {
printf("Greska pri otvaranju.\n"); //opening fault
}
for (j = 0; j < i; j++) {
fwrite(niz, sizeof(double), j, ulaz);
}
fclose(ulaz);
}
double srednja_vrijednost() {
double suma = 0;
if (i == 0)
return 0;
FILE *ulaz = fopen("niz.bin", "r");
if (!ulaz) {
printf("Greska pri otvaranju.\n");//opening fault
return 0;
}
double niz[100];
fread(niz, sizeof(double), i, ulaz);
int j;
for (j = 0; j < i; j++) {
suma += niz[j];
}
fclose(ulaz);
return suma / i;
}
int main() {
unesi_niz();
double n=srednja_vrijednost();
printf("%g\n", n);
return 0;
}
My code has several problems. the first is the wrong return value of the function srednja_vrijednost, when I enter the values 5 10 15, the result is 1.6667, which is nonsense, and then many "Profiler errors", my debug console says Error in line 56, main.c file: The program accesses a variable that is not initialized, however I don't see any "Forbidden Action".
Hope some of you can see what I have done wrong :)
Your code fails in unesi_niz at these lines:
for (j = 0; j < i; j++) {
fwrite(niz, sizeof(double), j, ulaz);
}
fwrite takes a pointer to the data, the size of individual elements in bytes and the number of such elements. This means your code writes j elements starting from the first element each time. You probably want to write 1 element each time. Or better yet, you want to write all i elements, since fwrite allows you to write more than one element.
fwrite(nix, sizeof(double), i, ulaz);
As an aside, your "srednja_vrijednost" logic will work, but only because you already know the size of your array in the current process (stored in i). I am not entirely sure what you are trying to do but I suspect you want to be able to read the same file back even after your process exits. For that, you would need some logic to find the size of the array. You can do this either by writing the length as well into the file, or (similar to the input) write an ending -1, or just figure out the size by calculating the file size.

1. Am I freeing memory correctly? 2. What's happening in the second for loop to cause an abundance of chars to be printed after the first iteration?

Am I freeing memory correctly in this program with just free(lineArr) at the end of main()?
I still can't figure out what's causing the issue with all the chars in my output (image attached). I know it's probably something basic with how I have the for loops set up.. things print correctly the first run after compiling, but not the second run. Why would this be?
Thanks
// When the sum of proper divisors for a number is the same as the number
// itself, the "status" of that sum may be considered "perfect"; when less,
// "deficient", and when greater than, "abundant".
//
// This program takes two extra command-line arguments after the executable
// name: an integer and a character. The integer will be the number of
// numbers past 2 to print statuses and histogram bars for; the character
// will be used to construct a histogram bar with height = to the sum of
// divisors for a particular number. Example arguments: ./a.out 6 '*'
// Example output:
// 2 is Deficient *
// 3 is Deficient *
// 4 is Deficient ***
// 5 is Deficient *
// 6 is Perfect ******
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int sumOfDivisiors(int aNum); //prototype for sumOfDivisiors function
typedef struct{ //define a structure called "line" with three members
int lineNum;
int sum;
char status[10];
}line;
int main(int argc, char *argv[]){ //main will accept command line arguments
int howMany;
char usrChar;
line whichLine;
if(argc < 3){
printf("Error: must enter 3 command line arguments.\n");
exit(1);
}
sscanf(argv[1],"%d", &howMany);
sscanf(argv[2], "%c", &usrChar);
line** lineArr = malloc(howMany * sizeof(line*)); //allocate mem for array of struct ptrs
if (lineArr == NULL){
printf("Error: trouble allocating memory. Exiting.\n");
exit(1);
}
for (int n = 2; n <= howMany; n++){ //loop to call func + initialize lineNum, sum, status for current line
int sumResult = sumOfDivisiors(n);
lineArr[n] = malloc(sizeof(line)); //allocate mem for pointer to current line struct
if (lineArr[n] == NULL){
printf("Error: trouble allocating memory. Exiting.\n");
exit(1);
}
line* temp = lineArr[n];
temp->lineNum = n;
temp->sum = sumResult;
if (temp->sum == n){
strcpy(temp->status, "Perfect");
} else if (temp->sum < n){
strcpy(temp->status, "Deficient");
} else {
strcpy(temp->status, "Abundant");
}
}
for (int i = 2; i <= howMany; i++){ //loop to print formatted results
printf("%3d %-10s ", i, lineArr[i]->status);
for (int j = 0; j < lineArr[i]->sum; j++){
printf("%c", usrChar);
}
printf("\n");
}
free(lineArr); //free dynamically allocated memory
return 0;
}
//Definition for sumOfDivisiors function. This function accepts an int number
//as an argument. It takes that number, finds all proper divisors (divisors
//less than the number itself), then returns the integer result of adding
//up all these divisors.
int sumOfDivisiors(int aNum){
int result = 0;
int i;
for (i = 2; i <= sqrt(aNum); i++){
if (aNum % i == 0){
if (i == (aNum/i)){
result += i;
} else {
result += (i + aNum/i);
}
}
}
return(result + 1);
}

Creating adjacency matrix from graph

I am trying to create an adjacency matrix from a graph file.
I need to read in a text file containing the number of vertices, then lists the graph format
Ex:
5
0 3 2
1 0 2
1 2 2
1 4 1
The first column of numbers is for the id of source vertex, the second column is for the id of target vertex, and the third column is the weight of edge
So this should return the matrix
0 2 0 2 0
2 0 2 0 1
0 2 0 0 0
2 0 0 0 0
0 1 0 0 0
So far I have read the text file and gotten the number of vertices but I'm not sure on what to do from here.
My current code:
#include <stdio.h>
#include <stdlib.h>
int main (){
printf("Enter the file contianing the graph\n");
char filename[20];
FILE *myFile;
scanf("%s",filename);
myFile = fopen (filename,"r");
int number_of_nodes, number_of_edges;
int source_id[100], target_id[100], weight[100];
int matrix[100][100];
int i;
if (myFile == NULL){
printf("File not found! Exiting...\n");
return -1;
}
else{
fscanf(myFile, "%d", &number_of_nodes);
printf("There are %d vertices.\n", number_of_nodes);
for(i = 0; i < (sizeof (source_id) / sizeof ( source_id[0] )); i++)
{
if( fscanf(myFile, "%d %d %d", &source_id[i], &target_id[i], &weight[i]) != 3)
break;
}
number_of_edges = i;
for (i = 0; i<99;i++){
for (int j = 0; j< 99; i++){
matrix[i][j]=0;
}
}
for (i = 0; i < number_of_edges; i++){
int x = source_id[i];
int y = target_id[i];
matrix[x][y] = weight[i];
matrix[y][x] = weight[i];
}
for (int y = 0; y < (number_of_nodes-1); y++){
for (int x = 0; x < (number_of_nodes -1); x++){
printf(matrix[x][y]);
printf(" \n");
}
}
}
fclose(myFile);
return 0;
}
Since you only posted the code for reading the file, I'll just comment on and improve that part.
First, you can define your variables in a better way. In the below code I removed your numberArray and instead, defined a number_of_nodes and three separate arrays for sources, targets and weights. This makes it easier to refer to these data later.
Second, since you don't have the number of items (edges) in the file, you must check if a read is successful by looking at the return value of fscanf(). It returns the number of elements that are successfully read. In your case, you're reading 3 numbers at a time, so you can just compare the return value with 3. You would also like to store the value of i after exiting the loop, so you'll know later how many edges are actually read.
Third, using scanf("%s") is as bad as using gets() (Why is it bad?). You should probably look into limiting the input length, for example using scanf("%19s"). I didn't fix it in the below code as it's not a direct issue, but should be taken into account in your later development.
And finally, +1 for your file open check. It's a good practice to ensure that previous actions completed successfully before proceeding.
Here's my fixed code:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Enter the file contianing the graph\n");
char filename[20];
FILE *myFile;
scanf("%s", filename);
myFile = fopen(filename, "r");
int number_of_nodes, number_of_edges;
int source_id[100], target_id[100], weight[100];
int i;
if (myFile == NULL) {
printf("File not found! Exiting...\n");
return -1;
}
else {
fscanf(myFile, "%d", &number_of_nodes);
printf("There are %d vertices.\n", number_of_nodes);
for (i = 0; i < (sizeof(source_id) / sizeof(source_id[0])); i++) {
if (fscanf(myFile, " %d %d %d", &source_id[i], &target_id[i], &weight[i]) != 3)
break;
}
number_of_edges = i;
}
fclose(myFile);
return 0;
}
For what to do next, I'll give you some tips instead of writing the full code directly. It's relatively easy if you get the point.
You would like to create a "matrix", or in the words of C, an array of arrays. To be simple, it should look like this
int matrix[100][100];
You can then initialize the matrix and reset it to zero:
// This is pseudo-code
for i = 0 to 99
for j = 0 to 99
matrix[i][j] = 0
And then based on what you have read from the file, you can assign the values to the zeroed-out matrix. Remember to assign two values (x to y and y to x)
for edge in edges
x = edge.source
y = edge.target
matrix[x][y] = edge.weight
matrix[y][x] = edge.weight
To print out the matrix, just go through it by row. Don't forget to print a newline after each row.
for y = 0 to (number_of_nodes - 1)
for x = 0 to (same as above)
print matrix[x][y] and a space
print a newline
If you can understand all the above ideas, then you're good to go.

Redirecting a file from stdin, using fgets() to read information to array

int main() {
#define MEMSIZE 100
int memory[MEMSIZE] = {0};
int i = 0;
char *temp = malloc(sizeof(100));
fgets(temp, MEMSIZE, stdin);
for (i = 0; i < (sizeof(memory)/sizeof(int)); i++) {
memory[i] = temp[i];
}
for (n = 0; n < 10; n++) { // Print contents
printf("%d - %d\n", n, memory[n]);
}
}
So today I have what seems to be a very simple question. I am taking a file from stdin, using:
./a.out < filename
My main goal is to take in the numbers provided in the file, and store them into a 1 dimensional array. My current use of fgets() works correctly, reading in line one and copying those elements into my 1D array (their ASCII values converted to int). Now, to read in my next lines, if I call fgets() again, the next line is read but it is then stored in the same place as the first values, thus overwriting them in my array in position 0-3. These values need to be stored successively in my array until EOF.
The file is in the format:
1234
5678
...
#include <stdio.h>
#define MEMSIZE 100
int main() {
int memory[MEMSIZE] = {0};
int i,n;
for (i = 0; i <MEMSIZE; i++){
if(fscanf(stdin,"%d", (memory+i))==EOF){
break;
}
}
//i is the number of ints you got
for (n = 0; n < i; n++) { // Print contents
printf("%d - %d\n", n, memory[n]);
}
return 0;
}
I dont see a reason to use dynamic allocation over here as a temp variable.
If the file is list of numbers, just read as a number, no need for fgets over here, if you still want to read it as a string, have a look at atoi func
sizeof(memory)/sizeof(int)= (sizeof(int)*MEMSIZE)/sizeof(int)= MEMSIZE
You shouldn't just loop MEMSIZE times, you need to know when it EOF
I dont know why you assumed in the printing loop that 10 is enough, i changed it to i which is number of elements
You didnt define n
I hope that i helped.

How to find the largest integer among an infinite number of integers in C

#include <stdio.h>
int main()
{
int res;
int max;
int i;
int Maximum;
for (i = 0 ; i < res; i++)
{
res = scanf("%d",&max);
if( res != 1 ) return 0;
if(max > Maximum)
{
Maximum = max;
}
}
printf("%d",&Maximum );
return 0;
}
Hi guys, I don't understand why Maximum prints out an obscene high number.
Just want a reason why, not something to hold my hand, for I really want to learn this language, I know Java mostly so what's happening here?
1. No need to pass address of integer variable.Else right now you are passing wrong argument to %d causes undefined behaviour.
printf("%d",&Maximum );
^ remove &
To print value of Maximum-
printf("%d", Maximum);
2. Maximum is unitialized in you program , therefore ,comparing it without initialization is incorrect.
int Maximum; // unintialized variable
Initialize it before using -
int Maximum=INT_MIN; // header <limits.h>
3. This loop of yours is not infinite. It will just iterate for 1 time -
for (i = 0 ; i < res; i++)
{
//your code
}
Instead use an infinite loop -
for(; ;){ // or while(1)
//your code
}
Initialize some value for the variable Maximum.
Maximum=0; // you can assign any value.
Then You have to change this line,
printf("%d",&Maximum );
into
printf("%d",Maximum );
&Maximum will give the address of the integer variable. While getting the input from scanf only we have to give like that.
Initialize Maximum to some value which is lowest for all the possible input values.
e.g. If input is guaranteed to contain only the positive integers then
Maximum = -1;
Or better use Maximum = INT_MIN; as pointed in comments. For that you'll need to include <limits.h> header file in your program.
printf("%d",&Maximum );
This is wrong. This will print the address of Maximum.
Use printf("%d", Maximum);
for (i = 0 ; i < res; i++)
res is not initialized! For an infinite numbers you'll want to make this loop infinite as while(1) or for( ; ; )
Because the program cannot know whether user will input only negative numbers, only positive numbers, or both, initializing "max" (or min) to a random number (such as zero) with the hope that it would "definitely" be maximum / minimum during the course of the execution, is likely to give erroneous results at some point.
The following is a simplistic approach that solely relies on user input, without trying to include any additional header files for absolute min / max values. It assumes the first provided input as "max", and if any subsequent entry surpasses that value, max is reset.
#include <stdio.h>
int main(void) {
int num, max;
int first_input = 1;
while(scanf("%d", &num) != EOF){
if(first_input){
max = num;
first_input = 0;
}
else{
if(max < num){
max = num;
}
}
}
printf("\n Maximum of the scanned numbers is: %d", max);
return 0;
}
The program will continue running until the user terminates the input by hitting Ctrl+D / Ctrl+Z.

Resources