Find largest and smallest number in array using pointers in C - c

I am writing a program that finds if either -l for find largest or -s for find smallest appears when the user inputs the string into the command line. For example ./a.out -l 2 4 6 would find the largest of the users input. In my program I am unsure if I should use atoi or if I can get by without. Also am I able to use the a pointer for the first part of my program and user the actual array in the second half to find the smallest or largest number? Since the ./a.out and -l is stored in array[0] and array [1] can I skip those and still find the largest and smallest numbers? I have written the code to find the largest and smallest number in an array but I am unsure if it is compatible. Any help would be appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
int x,i;
for(; *argv != '\0'; argv++){ //checks to see if -l is in string
if (strcmp(*argv,"-l") == 0){
x = 1; //easier to use x value than nested fors and ifs
break;
}
if(strcmp(*argv,"-s") == 0){ //checks if -s is in string
x = 2;
break;
}
else{ //if neither
printf("Error invalid option");
break;
}
}
if(x == 1){ //is going to find the largest element
for(i=2;i<argc;++i){
if(argv[2]<argv[i])
argv[2]=argv[i];
}
printf("Largest element is %d", argv[2]);
}
if( x == 2){ //find smallest element
for(i=2;i<argc;++i){
if(argv[2]>argv[i])
argv[2]=argv[i];
}
printf("Smallest element is %d", argv[2]);
}
return 0;
}

This is not a good idea.
char **argv is a pointer to an array of strings.
When you run your program with command line arguments, argc is initialised to the number of arguments passed, while argv will point to an array of string pointers pointing to the strings, somewhat like this:
The first argument is always the name of your executable, and the last element of argv is always grounded (set to NULL).
For more information, see here.
Using arithmetic operations on the elements of argv will actually carry out arithmetic on the pointers pointing to those strings, leading to behaviour you most likely don't want.
You must either fall back on using atoi() or write your own function to do so.

Your set of arguments is:
argv[0] "program_name"
argv[1] "-l" (or "-s") [program options]
argv[2] "<first_number>"
…
argv[argc-1] "<last_number>"
NULL
They are all read by the program as "C-strings", which are '\0' terminated character arrays in fact. So, char *argv[] is an a pointer to an array of character arrays. For more information please see this SO post and this SO post. There is no point in running a for loop (which is erratic in your case, btw) in order to detect which argument is the program option if you know it is the first, and the rest of your code shows you know.
If you are sure that the arguments to follow are numbers and you want to compare their arithmetic values, you first have to interpret them as numbers. atoi() is the function which returns the converted integral number string as int value. You also need the result values initialized to minimal or maximal value for the given data type. I don't see much use of incrementing pointers (*++argv) and a while loop in counting through arguments of main(). Using array subscriptions and a for loop are much easier to read. Here is a quick, though not entirely fool-proof fix of your code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
int main(int argc, char *argv[])
{
int x,i,m,n = 0;
if (strcmp(argv[1],"-l") == 0)
x = 1;
else if (strcmp(argv[1],"-s") == 0)
x = 2;
else{
printf("Error: invalid option");
return(1);
}
if(x == 1){ //is going to find the largest element
m = INT_MIN;
for(i=2;i<argc;++i){
if(atoi(argv[i]) >= m){
m = atoi(argv[i]);
n = i;
}
}
printf("Largest is the element #%d, equaling %d\n", n-1, m);
}
if( x == 2){ //find smallest element
m = INT_MAX;
for(i=2;i<argc;++i){
if(atoi(argv[i]) <= m){
m = atoi(argv[i]);
n = i;
}
}
printf("Smallest is the element #%d, equaling %d\n", n-1, m);
}
return 0;
}

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)

Summing an Array of Numbers but Receiving Error when Run [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am trying to sum an array of numbers. The array has a length determined by an input and then the user gives the array. There were no compilation errors and I am able to run other programs. On the immediate start of running the program I am given a message that program has stopped working and that windows is searching for solution.
#include <stdio.h>
int main()
{
int sum, length, count;
int array[length];
sum=0;
scanf("%d",&length);
scanf("%d",&sum);
for(count=0; count<length-1; count++)
{
sum = sum + array[count];
}
printf("%d", sum);
return 0;
}
When you declare your array it depends on length but you ask the user for length after.
A solution could be to ask the user for length (scanf("%d",&length);) before declaring your actual array (int array[length];).
you should move int array[length] to after scanf("%d", &length). But it is not allowed in C to declare variables after the first non-declaration (it is however possible if you compile this program as C++).
In fact, in standard C you can't have a non-const length definition for an array variable. gcc on the other hand for example allows this nevertheless.
In your case, the problem is that length has an undefined value at the declaration of int array[length];. If you are lucky, your data segment has been initialized to zero (there is no guarantee for that) but otherwise, it may be any value, including a value which leads the program to exceed your physical memory.
A more standard way of doing this is:
int *array = NULL;
scanf("%d",&length);
...
array = (int*) malloc(sizeof(int) * length);
...
free(array);
By the way, even after fixing that, you will most likely get random numbers because you never actually assign the contents of the elements of array.
Local variable are initialized to 0. Hence value of length is 0. So you array is of length. You are then reading length, say 10, from stdin and expect the array to be of length 10. This can't be. Since this is a stack variable, the size is determined in time of pre-processing and not in run time. If you want to define the array length in run time then use malloc.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int sum, length, count;
int *array;
sum=0;
scanf("%d", &length);
scanf("%d",&sum);
array = (int *)malloc(sizeof(int) * length);
if (array == NULL) return 0;
memset(array, length, 0);
for(count=0; count<length-1; count++)
{
sum = sum + array[count];
}
printf("%d", sum);
return 0;
}
Thanks.
first problem:
the length variable is being used to set the number of entries in the array[], before the variable length is set. Therefore, length will contain what ever trash happens to be on the stack when the program starts so the number of entries defined in array[] is an unknown.
This results in undefined behaviour and could lead to a seg fault event, depending on what was on the stack and what the user entered for length.
second problem:
The array array[] is never initialized so will contain what ever trash is on the stack at program startup. This means the value being printed could be anything. And the 'sum' could overflow, depending on the trash values in array[]
OP program lacks the part of data input, it's asking for sum instead of the values to sum, which is weird. The only inputs requested are also never checked (the return value of scanf must always be checked).
In C (at least C99 and optionally C11) Variable Length Arrays, like the one defined by int array[length], can be used, but the variable length here is used uninitialized and before it is even asked to the user.
Moreover, the loop where the sum is calculated stops before the last element of the array (not really a big deal in this case, considering that all those variables are uninitialized...).
A better way to perform this task could be this:
#include <stdio.h>
// helper function to read an integer from stdin
int read_int( int *value ) {
int ret = 0;
while ( (ret = scanf("%d", value)) != 1 ) {
if ( ret == EOF ) {
printf("Error: Unexpected end of input.\n");
break;
}
scanf("%*[^\n]"); // ignore the rest of the line
printf("Please, enter a number!\n");
}
return ret;
}
int main(void) {
int sum = 0,
length = 0,
count,
i;
printf("Please, enter the number of values you want to add: ");
if ( read_int(&length) == EOF )
return -1;
// Use a VLA to store the numbers
int array[length];
// input the values
for ( count = 0; count < length; ++count ) {
// please, note ^^^^^^^^ the range check
printf("Value n° %2d: ", count + 1);
if ( read_int(&array[count]) == EOF ) {
printf("Warning: You entered only %d values out of %d.\n",
count, length);
break;
}
// you can sum the values right here, without using an array...
}
// sum the values in the array
for ( i = 0; i < count; ++i ) {
// ^^^^^^^^^ sum only the inputted values
sum += array[i];
}
printf("The sum of the values is:\n%d\n", sum);
return 0;
}

Trying to find frequency of certain characters in a string but the results are very far off

I am trying to write a program which calculates and prints the GC content of a string of DNA(which is input through a txt file). That is, the percentage of G's and C's in a string of DNA. Here is my function for the GC percentage:
void updateGCCount(char s[], int *gc, int *at) {
char c[MAXLENGTH];
int i,GCcount,ATcount;
float len,GCpercentage;
GCcount=0;
ATcount=0;
for(i=0;c[i]!='\0';++i)
{
if(c[i]=='G' || c[i]=='C')
{
++GCcount;
*gc=GCcount;
}
if(c[i]=='A' || c[i]=='T')
{
++ATcount;
*at=ATcount;
}
}
strcpy(c,s);
len=strlen(c);
GCpercentage=*gc/len;
printf("GC-content: %.2f\n",GCpercentage);
}
This is my function definition, and the part which is supposed to correctly print the GC percentage is what I am not sure about. Below is my main program which utilizes the input text file.
#include "genomics.h"
int main(){
char s[MAXLENGTH];
int gc, at;
scanf("%s",s);
printf("Sequence : %s\n",s);
updateGCCount(s, &gc, &at);
return 0;
}
Any help or advice on why I am not getting a correct value for the GCpercentage would be great. Thank you in advance
You're doing your tests on char array "c":
char c[MAXLENGTH];
...
for(i=0;c[i]!='\0';++i)
{
if(c[i]=='G' || c[i]=='C')
{
++GCcount;
*gc=GCcount;
}
if(c[i]=='A' || c[i]=='T')
{
++ATcount;
*at=ATcount;
}
}
If should be on s, the array that you passed in. The c array is probably superflous, you should be able to get the length from s as well
c is not initialize, so *gc and *at are not updated at all and they contain garbage..
here you should use s instead of c
for(i=0;c[i]!='\0';++i)
{
if(c[i]=='G' || c[i]=='C')
{
++GCcount;
*gc=GCcount;
}
if(c[i]=='A' || c[i]=='T')
{
++ATcount;
*at=ATcount;
}
}
That's a strongly un-idiomatic program. Consider the following.
#include <stdio.h>
#include <stdlib.h> /* for exit(3) */
float count_gc(const char* s)
{
You have no need to pass information back via variables passed in by reference. Functions return values -- typically 'the answer'.
You're simply scanning the content of the argument string s, so there's no need to copy it anywhere.
As others have pointed out, you were scanning the contents of the array c[] before you copied anything in to it -- you were counting 'G' and 'C' in a (probably large) random block of memory. Keeping things simple avoids mistakes like that.
int nvalid = 0;
int gccount = 0;
float result;
for (; *s != '\0'; s++) {
Although the for loop you wrote isn't wrong, it's somewhat un-idiomatic. Here, we examine the character pointed to by the pointer s, and then increment the pointer, until we find ourselves pointing at the \0 that terminates the string. Yes, this means we 'lose' the initial value of the argument, but we don't need it after the loop, so that doesn't matter.
switch (*s) {
A switch is a more natural construction here. You're looking for a small set of possible values that *s (that is, the character the pointer is currently pointing at) may have.
case 'G':
case 'C':
nvalid++;
gccount++;
break;
case 'A':
case 'T':
nvalid++;
break;
default:
/* unexpected character -- ignore it */
break;
Every switch statement should have a default clause -- one should always think of what's supposed to happen if none of the case clauses match. In this case, we just ignore this character.
}
}
if (nvalid == 0) {
fprintf(stderr, "No valid letters found!\n");
result = 0.0;
} else {
/* Multiply by 1.0 to convert integer gccount to a float */
result = 1.0*gccount / nvalid;
}
return result;
We return the result to the caller rather than printing it out inside the function. Functions shouldn't 'chatter', but leave all of the I/O in one place, typically leaving the main function (or something higher up) to look after that.
}
int main(int argc, char** argv)
{
if (argc != 2) {
/* Give the user a hint on how to call the program */
fprintf(stderr, "Usage: gcat <string>\n");
exit(1);
}
printf("Sequence GC-content = %g\n", count_gc(argv[1]));
}
I run that with:
% cc -o gcat gcat.c
% ./gcat "GCAT ATx foo"
Sequence GC-content = 0.333333
%
With C, it's very easy to tie yourself in knots, very quickly. Aim for simplicity always.

Printing longer than calculated Average words in C program

I have a program that currently reads in words to a variable *char wordlist[lengthOfArray]; So basically it holds char word[10]. I can calculate average word lengths successfully, but I have a method that I want to print the words longer than this average recursively
void printAverage(char *wordlist, int n, int average){
if (n > 0){
if (strlen(wordlist[0]) > average){
printf("%s\n", wordlist[0]); // Print the one longer than average then move on
printAverage(wordlist + 1, n-1, average);
}
else {
printAverage(wordlist+1, n-1, average);
}
}
}
I have looked for hours online to see what is wrong, but for some reason, the comparison
if (strlen(a[0]) > average) isn't getting the value of my word correctly, and giving me the error
passing arg 1 of strlen makes pointer from Integer without a cast.
Does anyone have any idea how exactly I can do this correctly? Thanks in advance for any help, I am just stuck and I have already tried many things to no avail.
Your variable wordlist is not an array of words - it is a string. If you have an array of words it's either a 2D array like this:
char *wordlist[]
Or this:
char wordlist[][10]
Or a double-pointer like this:
char **wordlist
You need to set up the parameter according to the actual data you are passing into it.
You are declaring wordlist as a pointer to char instead of pointer to pointer to char.
char is an integral type so when you dereference it as wordlist[0] and pass it to strlen() the compiler warns you about passing an integral type instead of a pointer.
Try:
void printAverage(char **wordlist, int n, int average)
{
if (n > 0){
if (strlen(wordlist[0]) > average){
printf("%s\n", wordlist[0]); // Print the one longer than average then move on
}
printAverage(wordlist + 1, n-1, average);
}
}

Why does my palindrome function always return 1?

I'm writing a function for my homework which is supposed to tell if a given string is a palindrome or not.
Although I even tried it on paper with the word "otto", my program always returns 1.
Although this is a quite common question, I'd really like to know what I'm doing wrong instead of just copying a solution from here.
int is_palindrom(const char* palin)
{
int size = strlen(palin), i=0;
for (i=0;i<=(size/2); ++i)
{
if(palin[i] != palin[(size - i -1)])
{
return 1;
}
}
return 0;
}
Your code is correct, however please note that you may have an inverted logical expression. You are returning 1 in case of not equal, and 0 when it is. This means your function is working the opposite of "standard" C functions, where 1 evaluates to true.
Obviously, you are free to use whichever value you like to represent whatever you want. However, this can easily lead to confusion if someone else is reading your code. If bool is available, you should be using that; otherwise, you should always assume 1 is true and 0 is false.
Also, make sure to note is_palindrome takes a string and not an integer.
i.e. you must call it as is_palindrome("767") and not is_palindrome(767)
Your code does return 0 when it should. I am guessing when you read the string you pass as argument to your function, there are extra characters appended to the string, most probably a new line character. Try debugging the application or adding debug output in the function. For instance print the length of the string and the ascii codes of the characters in it.
Here is the code I used to verify it:
#include <stdio.h>
#include <string.h>
int is_palindrom(const char* palin)
{
int size = strlen(palin), i=0;
for (i=0;i<=(size/2); ++i)
{
if(palin[i] != palin[(size - i -1)])
{
return 1;
}
}
return 0;
}
int main(void) {
printf("%d", is_palindrom("otto"));
return 0;
}
Make sure your (const char *) has a "\0" at the end when you call this function.
#include<stdio.h>
#include<conio.h>
int is_palindrom(const char* jj);
int main(char *args){
int rr = is_palindrom("otto");
printf("rsult is %d", rr);
getch();
}
int is_palindrom(const char* palin)
{
int size = strlen(palin), i=0;
for (i=0;i<=(size/2); ++i)
{
if(palin[i] != palin[(size - i -1)])
{
return 1;
}
}
return 0;
}
I ran you code using above code snippet and it work fine for me.it returns 0 if palindrome is entered and 1 if entered value is not palindrome. the main part of the function is the loop
for (i=0;i<=(size/2); ++i) and the comparison if(palin[i] != palin[(size - i -1)]) the loop starts from 0 and then in condition palin[0] element and palin[4-0-1] i.e palin[3] element first o and last o in this case are mapped then the increement ++i takes place and then nest mapping of palin[second] and palin[second-last] elements happen so you can you either `++i' or 'i++'

Resources