I have an exercise of c - c

My exercise is input list integer numbers from keyboard and the end of program by 0. Then print sum of array. This is my code:
#include <stdio.h>
#include <stdlib.h>
const int MAX_ITEMS = 50;
void inputIntegerNumber(int* a, int* count);
int sumOfInteger(int* n, int* count);
int main(int argc, char** argv) {
int x[MAX_ITEMS], count;
inputIntegerNumber(&x, &count);
printf("Sum of array is %d", sumOfInteger(&x, &count));
return (EXIT_SUCCESS);
}
void inputIntegerNumber(int* a, int* count ){
do{
printf("Please! input numbers: ");
scanf("%d", a);
*count++;
}while((*a != 0) && (*count != MAX_ITEMS));
}
int sumOfInteger(int* n, int* count){
int sum = 0;
for (int i = 0; i < *count; i++)
sum += *n;
return sum;
}
I don't know what's wrong with it? It doesn't give me a result same my thinks...

There are some problems like -
inputIntegerNumber(&x, &count);
printf("Sum of array is %d", sumOfInteger(&x, &count));
in both calls you pass &x but x is an array of int and your function expects int * not int (*)[]. This must have given an error atleast.
For both functions you can just pass the array x directly.
And in your function inputIntegerNumber this -
*count++;
You need to increment value of count, so it should be (*count)++. Dereference first and then increment the value.

You are doing some mistakes in your code like passing pointer to a pointer &x value(since array is basically a pointer to some memory location) and overwriting the same location again and again. In scanf("%d", a); you are overwriting the first location again and again without changing a in you input loop.You need to learn about arrays and their usage. In sumOfInteger function also you're not changing the value of n. I changed you code a bit and i was able to see desired output.
#include <stdio.h>
#include <stdlib.h>
const int MAX_ITEMS = 50;
void inputIntegerNumber(int* a, int* count);
int sumOfInteger(int* n, int* count);
int main(int argc, char** argv) {
int x[MAX_ITEMS], count = 0; // zero elements in array
inputIntegerNumber(x, &count);
printf("Sum of array is %d", sumOfInteger(x, &count));
return (EXIT_SUCCESS);
}
void inputIntegerNumber(int* a, int* count ){
int aIndex = 0;
do{
printf("Please! input numbers: ");
scanf("%d", &a[aIndex]);
aIndex++;
}while((a[aIndex-1] != 0) && (aIndex != MAX_ITEMS));
*count = aIndex;
}
int sumOfInteger(int* n, int* count){
int sum = 0;
for (int i = 0; i < *count; i++)
sum += n[i];
return sum;
}
when i run it i can see :
~/Documents/src : $ ./a.out
Please! input numbers: 1
Please! input numbers: 2
Please! input numbers: 3
Please! input numbers: 0
Sum of array is 6

You're overcomplicating things. Before you sit down to write a program, always write the general steps that must be done
Read the numbers from the command line
Convert them to ints and save them in memory
Calculate the sum
Print it
Here is the revised program
#include <stdio.h>
#include <stdlib.h> /* for strtol */
#define DIE(msg) fprintf(stderr, "%s", msg); exit(EXIT_FAILURE)
int main(int argc, char *argv[])
{
int *nums;
if (argc <= 1)
DIE("Usage: [int-list]\n");
/* skip program name */
--argc;
++argv;
nums = malloc(argc * sizeof(int));
if (!nums)
DIE("Out of mem\n");
for (int i = 0; i < argc; ++i) {
char *end;
double val = strtol(argv[i], &end, 0);
if (end == argv[i]) /* no digits detected */
DIE("Usage: [int-list]\n");
nums[i] = val;
}
printf("%d\n", add(nums, argc));
free(nums);
}
int add(int arr[], size_t n)
{
int sum = 0;
for (int i = 0; i < n; ++i)
sum += arr[i];
return sum;
}
To complete the strtol error handling is an exercise for the OP.

Related

Segmentation Fault while printing

#include <stdlib.h>
#include <stdio.h>
#include "string.h"
//This function tries to calculate result of the floor function for floats <= 9999.
int main(int argc, char* argv[]) {
int i, j;
float k;
int x[10000];
for(i = 0; i < 10000; ++i){
x[i] = i;
}
printf("Enter a float in 0..9999: ");
scanf("%f", &k);
tester(x, k);
}
int tester(int* c, int k) {
printf("x[%d] = %d\n", k, c[k]);
}
When I run the program it gives me segmentation fault in here:
printf("x[%d] = %d\n", k, c[k]);
Can anyone see the what problem really is?
You can see the screenshots:
segmentation fault in printf
There are two major problems in your code.
You get input from the user (scanf) as float, but actually use it as int to pass it into the function and as index for the array x.
You should ALWAYS check user input from the terminal (or wherever). In this case the check should be at least, if the actual input is between 0 and 9999.
Improved version:
#include <stdlib.h>
#include <stdio.h>
#include "string.h"
void tester(int* c, int k) {
printf("x[%d] = %d\n", k, c[k]);
}
//This function tries to calculate result of the floor function for floats <= 9999.
int main(int argc, char* argv[]) {
int i;
int k;
int x[10000];
for(i = 0; i < 10000; ++i){
x[i] = i;
}
printf("Enter a float in 0..9999: ");
scanf("%d", &k);
if (k >= 0 && k < 10000) {
tester(x, k);
} else
{
printf("Sorry, your input %d was invalid.", k);
}
}
Probably that will fix your Segmentation Fault problem.

summing numbers using pointer arithmetic

I was given an assignment to write a code which takes in numbers as input from the user and provides the sum of it, specifically by the use of pointer arithmetic i.e. no array subscripting a[i] is allowed.
Below is the code that I wrote, which got compiled and even ran. But almost always it gives the sum of the input numbers as 0. I tried to fix it, but to no avail. Thus, I am asking for help, any help is greatly appreciated.
#include<stdio.h>
#define N 5
int sum_array( const int *p, int n)
{
int sum, a[N];
sum = 0;
for(p=&a[0]; p<&a[N]; p++)
sum += *p;
return sum;
}
int main()
{
int a[N], *i,x;
printf("Enter %d Numbers: ", N);
for(i=a; i<a+N; i++)
scanf("%d", i);
// all the input values get scanned as i or the array a
x= sum_array(i,N);
printf("the sum is %d\n", x);
return 0;
}
Beware, you are declaring array int a[N] in both main and sum_array. They are in different scopes, so they are different arrays (and the one from sum_array is never initialized so reading it invokes Undefined Behaviour).
The correct way is to pass the array along with its used length:
Here is a fixed version:
#include<stdio.h>
#define N 5
int sum_array( const int *a, int n) // a points to a array of at least n elements
{
int sum = 0; // initialize at definition time
for(const int *p=a; p<&a[n]; p++) // have the pointer p take all values from a
sum += *p;
return sum;
}
int main()
{
int a[N], *i,x;
printf("Enter %d Numbers: ", N);
for(i=a; i<a+N; i++)
scanf("%d", i);
// all the input values get scanned as i or the array a
x= sum_array(a,N); // pass the array address, not a pointer past last element
printf("the sum is %d\n", x);
return 0;
}
Finally it is mainly a matter of taste, but I was too often burnt for trying to add an instruction in a for loop without braces, so I strongly recommend using always braces for loops:
for(i=a; i<a+N; i++) {
scanf("%d", i);
}
int sum_array( const int *p, int n)
{
int sum = 0, i = 0;
for(i = 0; i < n ; i++)
sum += *(p+i);
return sum;
}
int main(void)
{
int a[N], i = 0, x = 0;
printf("Enter %d Numbers: ", N);
for(i=0; i<N; i++)
scanf("%d", a+i);
// all the input values get scanned as i or the array a
x= sum_array(a,N);
printf("the sum is %d\n", x);
return 0;
}
In x= sum_array(i,N); i is the iterator of your loop so after the loop has finished it points to the first position after the array.
You should pass the original array instead x= sum_array(a,N);
In the sum function you just throw away the passed pointer and replace it with your local a[].
int sum_array( const int *p, int n)
{
int sum = 0;
int *end = &p[n]; // first element after the array.
for(; p<end; p++) // just use p because you don't need the reference to the start of the array
{
sum += *p;
}
return sum;
}
but as you said that array notation is not allowed you can change it as follows
#include "stdio.h"
#define N 5
int sum_array( const int *p, int n)
{
int sum = 0;
const int *end = p+n; // first element after the array.
for(; p<end; p++)
{
sum += *p;
}
return sum;
}
int main()
{
int *a, *i, x;
a = malloc(N * sizeof(*a));
if (a == NULL)
exit(-1);
printf("Enter %d Numbers: ", N);
for(i=a; i<a+N; i++)
{
scanf("%d", i);
}
// all the input values get scanned as i or the array a
x= sum_array(a,N); // pass the array address, not a pointer past last element
printf("the sum is %d\n", x);
return 0;
}
in general, when programming, the code should be kept as simple as possible while still being complete.
The program criteria shows no need to keep a number after it is applied to the sum of the numbers, So in the proposed code, the input number is only kept long enough to be applied to the sum, then it is discarded.
The following proposed code:
cleanly compiles
performs the desired functionality
is kept very simple
properly checks for; and handles any errors
And now the proposed code:
#include <stdio.h> // scanf(), printf(), fprintf(), stderr
#include <stdlib.h> // exit(), EXIT_FAILURE
#define N 5
int main( void )
{
int num = 0;
int sum = 0;
printf("Enter %d Numbers: ", N);
for(size_t i=0; i<N; i++)
{
if( scanf("%d", &num) != 1 )
{
fprintf( stderr, "failed to read number\n" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
sum += num;
}
printf( "the sum is %d\n", sum );
return 0;
}

Segmentation fault without altering my program

I was trying to write a program that calculates prime numbers using threads and the program was working but not giving the desired results (it was telling all numbers were prime numbers). Today I tried to run the program again and I'm getting a segmentation fault even though I didn't alter my program. I tried using gdb to find when it was happening and I think it's happening on the pthread_join function.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int n_threads; // number of threads
int* numbers; // array of numbers
int elements_per_thread;
int isPrime(int n){
int i = 0;
for(i=0; i < n; i++)
if(n%i == 0)
return 0;
return 1;
}
void * threadPrime(void * arg){
int* idxp = (int*)arg;
int idx = *idxp;
int start = idx* elements_per_thread;
int finish = (idx+1)*elements_per_thread-1;
int i;
for(i=start; i<finish; i++)
if(!isPrime(i))
numbers[i]=0;
pthread_exit(NULL);
}
int main(int argc, char* argv[]) {
if (argc != 3) {
printf("usage: %s largest_number number_threads\n", argv[0]);
return 1;
}
int largest_number = atoi(argv[1]); // value of the largest number to test for primality
int n_numbers = largest_number-1; // number of numbers to test
n_threads = atoi(argv[2]);
// create and fill vector of numbers to test
numbers = (int *)malloc(n_numbers*sizeof(int)) ; // allocate a vector for n_numbers integers
int i;
for (i = 2; i <= largest_number; i++)
numbers[i-2] = i;
int* id = (int *)malloc(n_threads*sizeof(int));
// compute primes
pthread_t* thid = (pthread_t *)malloc(n_threads*sizeof(int));
for(i=0;i<n_threads;i++){
id[i] = i;
if(pthread_create(&thid[i],NULL,threadPrime,(void*)(id+i)) != 0){
printf("Erro\n");
exit(0);
}
}
for(i=0;i<n_threads;i++){
if(pthread_join(thid[i],NULL) != 0){
printf("Erro\n");
exit(0);
}
}
// print result
printf("Primes:");
int n_primes = 0;
for (i = 0; i < n_numbers; i++)
if (numbers[i]) {
n_primes++;
printf (" %d", numbers[i]);
}
printf("\nTotal: %d primes\n", n_primes);
return 0;
}
Problem solved. Correct code below.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int n_threads; // number of threads
int* numbers; // array of numbers
int elements_per_thread;
int isPrime(int n){
int i = 0;
for(i=2; i < n; i++)
if(n%i == 0)
return 0;
return 1;
}
void * threadPrime(void * arg){
int* idxp = (int*) arg;
int idx = *idxp;
int start = idx*elements_per_thread;
int finish = (idx+1)*elements_per_thread;
int i;
for(i=start; i<=finish; i++)
if(!isPrime(numbers[i]))
numbers[i]=0;
pthread_exit(NULL);
}
int main(int argc, char* argv[]) {
if (argc != 3) {
printf("usage: %s largest_number number_threads\n", argv[0]);
return 1;
}
int largest_number = atoi(argv[1]); // value of the largest number to test for primality
int n_numbers = largest_number-1; // number of numbers to test
n_threads = atoi(argv[2]);
// create and fill vector of numbers to test
numbers = (int *)malloc(n_numbers*sizeof(int)) ; // allocate a vector for n_numbers integers
int i;
for (i = 2; i <= largest_number; i++)
numbers[i-2] = i;
int* id;
id = (int *)malloc(n_threads*sizeof(int));
// compute primeselements_per_thread = n_numbers/n_threads;
elements_per_thread = (n_numbers/n_threads)+1;
pthread_t* thid = malloc(n_threads*sizeof(*thid));
for(i=0;i<n_threads;i++){
id[i] = i;
if(pthread_create(&thid[i],NULL,threadPrime,(void*)(id+i)) != 0){
printf("Erro\n");
exit(0);
}
}
for(i=0;i<n_threads;i++){
if(pthread_join(thid[i],NULL) != 0){
printf("Erro\n");
exit(0);
}
}
// print result
printf("Primes:");
int n_primes = 0;
for (i = 0; i < n_numbers; i++)
if (numbers[i]) {
n_primes++;
printf (" %d", numbers[i]);
}
printf("\nTotal: %d primes\n", n_primes);
return 0;
}
There are a number of issues:
1) The starting index for the loop should be 2. Otherwise, you are going to have divide by zero error here:
for(i=0; i < n; i++) // should be i=2
if(n%i == 0)
return 0;
2) elements_per_thread is not set at all. So it's going to be 0 (since it's a global variable) and the loops in thread function will never be called. Set it in main():
elements_per_thread = n_numbers/n_threads;
3) When you call isPrime() you are passing i. But you really wanted to pass numbers[i]. You also want to include the finish in the primality test. So it should be
for(i=start; i<=finish; i++)
if(!isPrime(numbers[i]))
numbers[i]=0;
4) The allocation for thread array is wrong. It should be
pthread_t* thid = malloc(n_threads * sizeof *thid);
There are more efficient ways to test primes (e.g. you only need to check upto n/2 to see if it's prime). But once you fix the above issues, you'll have a working code and think about improving it later.
You didn't allocate the right amount of memory for thid. This is the main reason for your segmentation fault.
pthread_t* thid = (pthread_t *)malloc(n_threads*sizeof(int));
should be
pthread_t* thid = malloc(n_threads*sizeof(p_thread));
(you don't need to cast malloc in C)
This is why I don't usually use an explicit type as the operand of sizeof, and instead just use the variable name so that the compiler can deduce the type itself.
pthread_t* thid = malloc(n_threads*sizeof(*thid));

How do I loop and print through an array of structs in c?

I am writing a function separate from main that reads in an array of structs and prints each array element's struct elements. My problem however is the condition statement for looping though this array to print each element. sizeof(a)/sizeof(a[]) just doesnt work in the function because it is equal to zero within the prototype. Is there something i am missing? I've tried pointer arithmetic and it does not work either.
void printNames( person a[]){
int i;
for(i = 0;i<sizeof(a)/sizeof(a[0]);i++)
printf("Name: %s | Age: %d\n", a[i].name, a[i].age);
}
int main(int argc, char *argv[]){
if (argc == 1 || argc%2 == 0){
printf("Invalid arguments.\n Usage: %s name1 age1 name2 age2 ...", argv[0]);
return 0;
}
printf("You have entered %d person(s) into the program.\n", argc/2);
person people[argc/2];
int i;
for (i = 0; i<argc/2;i++){
strcpy(people[i].name, argv[i*2+1]);
people[i].age = atoi(argv[i*2+2]);
if(people[i].age <= 0){
printf("Invalid age <= 0. Try again.");
return 0;
}
}
a becomes a pointer when passed as parameter to a function, so it cannot figure out the size of the array just from having this pointer, you have to inform the function about its size:
void printNames(person *a, size_t num)
{
int i;
for (i = 0; i < num; i++)
printf("Name: %s | Age: %d\n", a[i].name, a[i].age);
}
Then call printNames from main like this:
printNames(people, sizeof(people)/sizeof(*people));
In C, array parameters are decayed into pointers. So, the expression sizeof(a)/sizeof(a[0]) becomes sizeof(int *)/sizeof(int) which results in 1 (assuming the size of int and int * is 4) and hence the for loop within the printNames() is executed only once regardless of the size of the array.
Therefore, sizeof shouldn't be used to obtain the number of elements in these cases. Instead, we can pass an additional parameter for array size to printNames().
Consider the following C program:
#include<stdio.h>
void func(int array[])
{
int i;
int arraySize = sizeof(array)/sizeof(array[0]); /* arraySize <-- 1<-- 4/4 */
for (i = 0; i < arraySize; i++)
{
array[i] = i;
}
}
int main()
{
int i;
int array[4] = {0, 0 ,0, 0};
func(array);
for(i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
printf(" %d " ,arr[i]);
getchar();
return 0;
}
Output: 0 0 0 0 on a Intel Architecture-32 machine.
So the corrected program is:
#include<stdio.h>
void func(int array[], size_t arraySize)
{
int i;
for (i = 0; i < arraySize; i++)
{
array[i] = i;
}
}
int main()
{
int i;
int array[4] = {0, 0 ,0, 0};
func(array, 4);
for(i = 0; i < sizeof(array)/sizeof(array[0]); i++)
printf(" %d ", array[i]);
getchar();
return 0;
}

storing input into malloc array (1d and 2d) and printing

I am tryin to take input from the user and store it into an array and print it out: i have 2 functions:
/* Read a vector with n elements: allocate space, read elements,
return pointer */
double *read_vector(int n){
double *vec = malloc(n * sizeof(double));
int i;
for (i = 0; i < n; i++)
vec[i] = n;
return vec;
}
and the print function is:
void print_vector(int n, double *vec){
int i;
for (i = 0; i < n; i++) {
printf("%d\n", vec[i]);
}
}
the main function is:
#include <stdio.h>
#include <stdlib.h>
double *read_vector(int n);
void print_vector(int n, double *vec);
void free_vector(double *vec);
int main(){
int n;
double *vector;
/* Vector */
printf("Vector\n");
printf("Enter number of entries: ");
scanf("%d", &n);
printf("Enter %d reals: ", n);
vector = read_vector(n);
printf("Your Vector\n");
print_vector(n,vector);
free_vector(vector);
}
when i run this, it does not let me enter any numbers, it just skips it and prints out 0's. How do i fix this?
Try the code below. You're almost certainly either not compiling with warnings, or ignoring the warnings. All warnings mean something, and to a beginner they all matter. With gcc use the -Wall option, or even -pedantic.
As halfelf pointed out, you need a scanf in your read loop but it needs to be a pointer (&vec[i]). Always return something at the end of main. Also check the return value of malloc, it could fail and return a null pointer.
#include <stdio.h>
#include <stdlib.h>
double *read_vector(int n)
{
double *vec = malloc(n * sizeof(double));
int i;
for (i = 0; i < n; i++) {
printf("Enter number %i of %i: ", i + 1, n);
scanf("%lf", &vec[i]);
}
return vec;
}
void print_vector(int n, double *vec)
{
int i;
for (i = 0; i < n; i++) {
printf("%f\n", vec[i]);
}
}
void free_vector(double *vec)
{
free(vec);
}
int main()
{
int n;
double *vector;
printf("Vector\n");
printf("Enter number of entries: ");
scanf("%i", &n);
vector = read_vector(n);
printf("Your Vector\n");
print_vector(n, vector);
free_vector(vector);
return 0;
}
In the read_vector(int n) function's for loop:
for (i=0; i<n; i++)
vec[i] = n; // this should be scanf("%lf",vec+i) to read input from stdin
and notice your { and } there. If there's only one line in the loop, { and } is not necessary, OR you have to use a pair of them. The return clause must be out of the loop.
Btw, add return 0 at the end of your main function.
simple..you forgot to write scanf..!
double *read_vector(int n)
{
double *vec = malloc(n * sizeof(double));
int i;
for (i = 0; i < n; i++)
scanf("%d",&vec[i]);
return vec;
}

Resources