Function to count the sum of an array - c

Right, this is (the last) assignment for my C introduction web class.
The assignment presents the main program, does not explain anything about it and tells you to write a function to print and sum the array in it.
However I don't really understand what is going on in the main program.
Translated for your convenience;
Source code:
#include <stdio.h>
#include <stlib.h>
void print_count(int *, int);
int main(int argc, char *argv[]) {
int x, sum = 0, size = 0, array[5];
if (argc == 6) {
/* Program name and parameters received from command line */
for (x = 0; x < argc - 1; x++) {
array[x] = atoi(argv[x + 1]);
}
print_count(array, size);
} else {
printf("Error\n");
}
return 0;
}
Now I am completely clueless as to how to start writing the program requested and what variables to call/how to write the function.
Edit3: completed exercise
void print_count(int *array, int size) {
int i;
int sum = 0;
printf("Elements: ");
for (i = 0; i <= size; i++) {
printf("%d ", (array[i]);
sum = sum += array[i]);
}
printf("\nSum = %d ", sum);
return 0;
}
I would like to understand what is going on in the main program and preferably come to an answer on how to actually write the function by myself.

This:
array[5] = atoi(argv[x+1]);
is clearly wrong, it always tries to assign to array[5] which is out of bounds. It should be:
array[x] = atoi(argv[x + 1]);
This converts the x + 1:th argument from string format into an integer, and stores that in array[x]. If you're not familiar with the standard function atoi(), just read the manual page.
So if you start the program like this:
./myprogram 1 2 3 4 5
That has 6 arguments (the first is the name itself), and will end up with array containing the numbers one through five.
Then in the summing function, the first line should be something like:
void print_count(int *array, int size)
so that you give names to the arguments, which makes them usable in the function. Not providing names is an error, I think.
And it doesn't need to "interact" with main() more than it already does; main() calls print_count(), passing it a pointer to the first element of array and the length of the array, that's all that's needed to compute the sum.

Your print_count function has a few issues:
The loop runs one step too far: i should vary between 0 and size-1 included. The standard idiom for this loop is:
for (i = 0; i < size; i++) {
...
Incrementing sum is simply done with:
sum += array[i];
There is an extra ( on the first printf line.
You should print a newline after the output.
Returning 0 from a void function is invalid.
Here is a corrected version:
void print_count(int *array, int size) {
int i;
int sum = 0;
printf("Elements: ");
for (i = 0; i < size; i++) {
printf("%d ", array[i]);
sum += array[i]);
}
printf("\nSum = %d\n", sum);
}

the following proposed code:
cleanly compiles.
explains what is being accomplished at each step of the 'main()' function.
properly outputs error messages to 'stderr'.
implements the typical method to announce an error in the number of command line parameters.
Now the proposed code with explanatory comments:
#include <stdio.h> // printf(), fprintf()
#include <stdlib.h> // atoi(), exit(), EXIT_FAILURE
void print_count(int *, int);
int main(int argc, char *argv[])
{
if (argc != 6)
{
fprintf( stderr, "USAGE: %s int1 int2 int3 int4 int5\n", argv[0] );
exit( EXIT_FAILURE );
}
// implied else, correct number of arguments
// only declare variables when they are needed
int array[5];
// place each command line parameter into 'array',
// except program name
// I.E. skip the program name in argv[0]
for( int i = 1; i < argc; i++ )
{
// array[] index starts at 0, but loop counter starts at 1
array[i-1] = atoi(argv[i]);
} // end for( each value pointed at by argv[], except program name )
// print sum of command line parameters to stdout
int size = argc-1; // number of command line parameters after program name
print_count(array, size);
return 0;
} // end function: main

Related

Is there another way to represent fscanf's 3rd argument in this code?

I am having a bit of difficulty understanding the arguments for fscanf. The first two are self-explanatory. The first argument is the point file. It gets the content from this file. The second argument is the type of content in the file. In this case it's int so there is usage of %d. Now, the third argument, I am having difficulty discerning and it would help to have it done in some other way, so I can better understand what this 3rd argument is all about.
#include <stdio.h>
#include <string.h>
int main(void);
void getCode(char a[]);
int getMessage(int a[]);
void sortMessage(int a[], int b);
void decodeMessage(char a[], int b[], int c);
int main(void) {
// declare file names
char string[53];
int integers[27];
int msgSize;
// int codeSize = 52;
// Open files & there content
getCode(string);
msgSize = getMessage(integers);
sortMessage(integers, msgSize);
decodeMessage(string, integers, msgSize);
}
void getCode(char string[]) {
// get content from code file & print it
FILE *C = fopen("codefile.txt", "r");
while (fgets(string, 55, C)) {
printf("%s\n", string);
}
}
getMessage(int integers[]) {
// Get content from message file & return it
FILE *M;
M = fopen("msgfile.txt", "r");
int counter = 0;
/* Read one number at a time from the file and store it */
while (!feof(M)) {
fscanf(M, "%d", (integers + counter));
counter++;
}
/* Close the file */
// fclose(M);
return (counter);
}
The third, and subsequent parameters if used, are pointers to the destinations of the parsed values. The better way to write that is &arrayname[index] because it more clearly indicates you are using a type size array index as a pointer. Note that newlines are just like any other whitespace.
Try this yourself
Single Example :
#include <stdio.h>
void main()
{
int count=3;
int ints[3];
printf("Give me %d:\n",count);
for (int i=0;i<count;i++)
scanf("%d",&ints[i]);
printf("You said:\n");
for (int i=0;i<count;i++)
printf("%d\n",ints[i]);
}
Result:
Give me 3:
12
23
34
You said:
12
23
34
Multiple Example: (which could allow you to mix types, or fork into more arrays).
#include <stdio.h>
void main ()
{
int count = 6;
int ints[6];
printf ("Give me %d :\n", count);
for (int i = 0; i < count; )
{
int got;
got= scanf ("%d %d %d", &ints[i], &ints[i + 1], &ints[i + 2]);
i+= got;
}
printf ("You said:\n");
for (int i = 0; i < count; i ++)
printf ("%d\n", ints[i]);
}
Result:
Give me 6 :
1 2 3
4
5 6
You said:
1
2
3
4
5
6

Need to be "pointed" in the right direction beginning C programming

and thanks for your time. I apologize in advance I am new to C programming and posting on stack overflow. Any information I may have left out and questions you have please ask.
I have this lab I am working on for my class and I'm having trouble understanding how the dreaded pointers operate. First I will explain the lab instructions.
First, I am to create an array of 200 words with a max length of 30+1 for null.
Next, call functions I need to create which include:
A read function which reads words from a file into the array. I must use fopen and fscanf functions.
A function to convert a string to lowercase using the ASCII codes of each character. (Must use pointers)
A function to return the length of a string.(Can't use strlen function and must use pointers)
A function with three parameters(array of words, # of words in array, and an int length). Function returns the number words in the array that match the int length.
A print function to print all the words in the array.
The IDE I am using is Dev C++ its been wonky so I have also been using netbeans.
I have only attempted to create the read, print, and converting to lowercase functions. I first tried to read the file and print the array in main. The file I'm reading is created by me it contains a short sentence which follows exactly:
There ARE so MANY words in HERE
EDIT- Updated main code to current with working lowercase loop inside main.
#define rows 200 //How many words allowed in array.
#define cols 31 //How many characters allowed for each word.
void lowercase(char* words, int count);
int read(char (*words)[cols]);
void print(char (*words)[31], int count);
int main(int argc, char *argv[]){
char words[rows][cols];
int i, j;
int count = read(words);
print(words, count);
/*
//make words lowercase
for(i = 0;i<count;i++){
for(j = 0;j<cols;j++){
if(words[i][j]!=0){
if(words[i][j]<91 && words[i][0]>64)
words[i][j] = words[i][j]+32;
}
}
}*/
for(i = 0;i < count;i++){
lowercase(*words+i, count);
}
print(words, count);
return 0;
}
The code is poorly written and managed properly I'm just trying to get everything to work first then it will be more appropriate. The first printf output comes out how it should:
Array [0]: There
Array [1]: ARE
Array [2]: so
Array [3]: MANY
Array [4]: words
Array [5]: in
Array [6]: HERE
Then the print function I have prints out the words correctly in the array but it includes all 30 spaces for each word instead of just the word. This is how it is written I need to change it.
void print(void *array, int SIZE){
int i,
j;
char *charArray = (char *) array;
for( j = 0; j < SIZE; j++ ){
for( i = 0; i < SIZE; i ++){
printf( "%c ", charArray[j*SIZE + i] );
}
printf( "\n" );
}
}
The tolower function I created was partially working converting the first letter of each word to lowercase. Now it is broke and do not remember what I have changed.
EDIT- updated lowercase function. The lowercase in main works exactly but with this function it doesn't convert all the words to lowercase it stops at the third word the rest are the same.
void lowercase(char *words, int count){
int j;
for(j = 0;j<cols;j++){
if(words[j]!=0){
if(words[j]<91 && words[j]>64)
words[j] = words[j]+32;
}
}
}
I tried to move the read code in main to its own function also trying to mimic the print code with the pointers but when I run the program it stalls and the exe file stopped working window pops up with command prompt.
No errors or warnings in IDE.
int read(void *array){
FILE *file;
int i,
j;
char *words = (char *) array;
file = fopen("words.txt", "r");
//STORE IN ARRAY
for(i=0;i<7;i++)
fscanf(file,"%s", words[i]);
}
If you have not figured out I have no idea when or how to use pointers or addresses. I have been taught basically all of C in literally 12 hours which is in my opinion not enough time to learn the language at all especially understand it efficiently. Any help will be greatly appreciated. Thank You.
By casting a 2-dimensional array down to a char*, you have lost some information. If you read the words in correctly, then in memory, your array might look like this:
0 10 20 30
|.........|.........|.........|.
There
ARE
so
MANY
words
in
HERE
To access words[1] the compiler is automatically offsetting 31 bytes from the beginning of the array.
Your problem is that after you cast words to char*, then the compiler no longer knows about the 2D structure, and words[1] will now only offset 1 byte from the beginning of the array.
A simple solution is to redefine your read function:
int read(char words[][31])
{
FILE *file;
int i, j, count = 0;
file = fopen("words.txt", "r");
for (i=0; i<7; i++)
{
count += (1 == fscanf(file, "%s", words[i]));
}
return count;
}
Now the compiler knows that the memory stride size for words[i] is 31 char values.
Similar thing with print:
void print(char words[][31], int count)
{
int i;
for( i = 0; i < count; i ++)
{
printf( "%s\n", words[i] );
}
}
fix like this:
#include <stdio.h>
#include <stdlib.h>
//Stringification
#define S_(n) #n
#define S(n) S_(n)
//Information to be shared across the whole area
#define MAX_ROWS 200
#define MAX_WORD_LENGTH 30
#define COLS (MAX_WORD_LENGTH + 1)
#define DATA_FILE "words.txt"
int read(void *array);
void print(void *array, int rows);
int main(void){
char words[MAX_ROWS][COLS];
int rows;
rows = read(words);
print(words, rows);
return 0;
}
int read(void *array){
FILE *file = fopen(DATA_FILE, "r");
if(file == NULL){
perror("fopen:");
exit(EXIT_FAILURE);
}
char *words = array;
int rows;
for(rows = 0; rows < MAX_ROWS; ++rows, words += COLS){
if(fscanf(file, "%" S(MAX_WORD_LENGTH) "s", words) == EOF)
break;
}
fclose(file);
return rows;
}
void print(void *array, int rows){
char *words = array;
for(int r = 0; r < rows; ++r, words += COLS){
printf("Array [%d]: %s\n\n", r, words);
}
}

C - How would I extract Even numbers from an array and place them into another array called EvenNumbers?

I'm tasked with writing a function that will identify all the even numbers in an sample array {10,2,9,3,1,98,8] and place them in an array called EvenNumbers. I have to allow the function so that it works with different combinations of numbers in the array not just the numbers in the sample array above.
I'm wondering is there any way to add numbers to an array that could be different every time? How would I extract the even numbers an place them into an array? Also
for the even array size its giving me an error that the expression must have a constant value but when I use const int it still gives me that error.
Here is the full question.
"Using the array of sample values {10,2,9,3,1,98,8}, write a function that will identify all the even numbers in an array and place it in an array called EvenNumbers. The function must work in all cases, not just in the case of the array shown. Assume that the array size is always available through a global constant called MAX"
Here is what I have so far. I've no idea how I will extract the even numbers from a for loop and place them in an array. I also dont know what the "expression must have a constant value" is about?
#include <stdio.h>
#include <stdlib.h>
void EvenNumber(int Array[], int size);
int main()
{
int array[7] = { 10,2,9,3,1,98,8 };
EvenNumber(array, 7);
}
void EvenNumber(int Array[], int size)
{
int i;
int EvenArraySize;
for (i = 0; i < size; i++)
{
if (Array[i] % 2 == 0)
{
EvenArraySize++;
}
}
int Even[EvenArraySize];
}
The right way to go is to use malloc to allocate just the right amount of memory.
Count the number of even numbers
Allocate the space needed to store them
Copy even numbers in this space
Do whatever you want with these numbers
Free the allocated space
Snippet:
#include <stdio.h>
#include <stdlib.h>
#define MAX 7
int
main()
{
int array[] = {10,2,9,3,1,98,8};
int *even_numbers;
int i, nb_even_numbers;
for (i = 0, nb_even_numbers = 0; i < MAX; i++)
{
if (array[i] % 2 == 0)
nb_even_numbers++;
}
even_numbers = malloc(sizeof(int) * nb_even_numbers);
if (!even_numbers)
{
perror("malloc");
return 1;
}
for (i = 0, nb_even_numbers = 0; i < MAX; i++)
{
if (array[i] % 2 == 0)
even_numbers[nb_even_numbers++] = array[i];
}
/* do your stuff here */
free(even_numbers);
return 0;
}
First, you can never return a statically declared array from a function (even though you don't explicitly try, your Even array is destroyed when EvenNumber returns) Why? The function stack frame for EvenNumber is released for reuse on return and any locally declared arrays are no longer valid.
You either need to pass a second array as a parameter to EvenNumber, or you can dynamically allocate storage for Even in EvenNumber (with, e.g. malloc or calloc or realloc) and return a pointer to the beginning of the array. (you must also have some way to return the size or use a constant for a max size).
There is no need to use % (modulo) to test whether a number is odd/even. All you need to do is look at bit-0 (little endian). If it is 0, then the number is odd, if it is 1, then its even. Much more efficient than calling modulo which incorporates division.
Finally, main is type int and therefore returns a value.
Putting those pieces together, you can do something simple like the following:
#include <stdio.h>
#include <stdlib.h>
void EvenNumber (int *array, int *even, int size, int *esize);
int main (void)
{
int array[] = { 10,2,9,3,1,98,8 },
i, n = sizeof array / sizeof *array,
even[n], /* a VLA of the same size as array is fine here */
esize = 0;
EvenNumber (array, even, n, &esize);
printf ("array: ");
for (i = 0; i < n; i++)
printf (" %2d", array[i]);
printf ("\neven : ");
for (i = 0; i < esize; i++)
printf (" %2d", even[i]);
putchar ('\n');
return 0;
}
void EvenNumber (int *array, int *even, int size, int *esize)
{
int i;
for (i = 0; i < size; i++)
if ((array[i] & 1) == 0) /* simply looking at bit-0 is all you need */
even[(*esize)++] = array[i];
}
Note: esize is passed as a pointer to EvenNumber and updated within the function so that the number of elements in even are available back in the calling function (main() here).
Example Use/Output
$ ./bin/arrayeven
array: 10 2 9 3 1 98 8
even : 10 2 98 8
Let me know if you have any further questions.

Command line number adding program produces wrong results

My Code:
#include <stdio.h>
int main(int argc, char*argv[]){
int n = argc;
int i, a, b, sum;
for(i = 0; i < n; i++){
sscanf(argv[i], "%u", &a);
b = a + sum;
sum = b;
}
printf("%d\n", sum);
return 0;
}
This piece of code should do ./a 0 1 2 3 must write terminal 6 But writes 42423.
The aim of the program was to issue the command-line arguments amount. But he does not make it correct angulation.
argv[0] holds the name of the executable which most likely you don't want to include in the loop. so, you need to start the loop from i=1.
As per your input, the argv[0] does not contain a numeric value hence causing a failure to sscanf(), leaving a uninitialized.
So, in your code, the primary issue is with,
b = a + sum;
where, for the first iteration, a and sum are both uninitialized local variables having indeterminate value. So, for the very first loop, you're invoking undefined behavior.
Also, a being an int, you need to use %d format specifier for it.
Two things to mention:
Always check for the return value of scanf() family for success.
Always initialize your local variables.
You are getting garbage value because you are not initialized varuiable sum on declaration.
Just initialize is as sum = 0 and u will get expected result.
Or u can use below code also.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char*argv[]){
int n = argc;
int i, a, b, sum=0;
for(i = 0; i < n; i++){
a = atoi(argv[i]);
sum += a;
}
printf("%d\n", sum);
return 0;
}

Counting substrings in a string

I have the task to make a little program with pointers and I am facing a problem with const char*s. The program is meant to count the number of times that a sub-string appears in a main-string. Also, the different positions, where the sub-strings start, should be saved in a char** ptr. This is my little testing code:
#include <stdio.h>
#include <string.h>
main()
{
int i=-1;
int k=0;
char** ptr;
char* str="cucumber";
char* substr="cu";
while(strstr(str, substr)!=NULL)
{
i++;
ptr[i]=strstr(str, substr);
str = strpbrk(str, substr)+1;
k++;
}
printf("%i",k);
}
It should print 2, since the sub-string 'cu' appears 2 times in 'cucumber' - yet, my compiler tells me that I am using chars, when I should use constant ones. Except, I don't know how to do that.
The strstr() function requires them. What should I change?
// note:
// 1) correction to declaration of main()
// 2) addition of return statement
// 3) 'substr' is a poor name choice for a variable, as
// a) it looks like a C lib function (it is a ACL library function)
// b) it does not clearly convey what the variable contains
// 4) clutter in the 'while' loop removed
// 5) 'while' loop is replaced by a 'for' loop so more can be accomplished with less code
// 6) unneeded variables are eliminated
// 7) the 'for' loop stops when there is no possibility of further testStr occurrences
// 8) the printf() clearly indicates what is being printed
#include <stdio.h>
#include <string.h>
int main()
{
char* testStr="cucumber";
char* findStr="cu";
int k = 0;
for( int i=0; strlen(&testStr[i]) >= strlen(findStr); i++)
{
if( strstr(&testStr[i], findStr) != NULL)
{
k++;
}
}
printf("\nnumber of occurrences of %s in %s is %d\n", findStr, testStr, k);
return(0);
}
Allocate memory for storing the pointer values
#include <stdio.h>
#include <string.h>
#define MAX_SUB_STR 10
int main()
{
int i;
int k;
char* ptr[MAX_SUB_STR];
char* str="cucumber";
char* temp;
char* substr="cu";
i = 0;
k = 0;
temp = str;
while(strstr(temp, substr)!=NULL && k < MAX_SUB_STR)
{
ptr[k]=strstr(temp, substr);
temp = ptr[k] + strlen(substr);
k++;
}
printf("%i\n",k);
for (i = 0; i < k; i++)
printf("%p\n",ptr[i]);
return 0;
}

Resources