C - How to read input separated by commans and whitespaces - arrays

I have a question on how to read input and assigning it to an array (or even two arrays).
I have a project where I have to:
Create a C console application to compile the following statistics on a list of real number pairs:
• minimum value;
• maximum value;
• median value;
• arithmetic mean;
• mean absolute deviation – (mean, median, mode)
• variance (of a discrete random variable);
• standard deviation (of a finite population);
• mode (including multi-modal lists).
• least squares regression line
• outliers
Your program must handle any length of list. The list will be input (or piped) from the console, or read from a file. The list is terminated with end-of-stream (^Z) or non-numeric input.
So basically, the program has to read:
1,2
2,23
3,45
5,34
or: 1,2 3,4 5,6 7,8
and be able to calculate their statistic properties.
I know how to do the calculations and create the functions etc. My question is, how to implement the parts: "any length of the list" and "list of real number pairs". See sample below.
sample output
What I tried so far:
#include <stdio.h>
int main()
{
int a[100];
int b[100];
int n = 100;
for (int i = 0; i < n; i++) {
scanf_s("%d,", &a[i]);
}
for (int i = 0; i < n; i++) {
printf(" %d", a[i]);
}
return 0;
}
which returns a the result, but only to a fixed array length and gives me a bunch of -858993460 -858993460.
For now, I just want to know how to read the input properly and assign them to one Array, so I can read the odd and even index and calculate their mean and whatever respectively...
or assign them to two different arrays (x[], y[]), x for the digit on the left of the comma, y on the right.

Hi you can get the entire input in a single line in a character array and then loop on the array to correctly split the char array to convert it into integer array.
Below is the code you can try :
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
char *src = (char*)malloc(sizeof(char) * 500);
fgets(src, 500, stdin);
int arr[500];
int index = 0;
int n;
while ( sscanf ( src, "%d%n", &arr[index], &n ) == 1 ) {
//while ( sscanf ( src, "%d,%n", &arr[index], &n ) == 1 ) { ////Use this for values separated by commas
printf("%d\n", arr[index]);
index++;
src += n;
}
return 0;
}

Related

The output is weird on my C Console App. Any ideas?

I want to make an app that determines whether the given input is a positive number, and then prints them out if there are more than 2 positive numbers, but there is a weird output which I've been trying to fix for a few hours.
Note : I'm somewhat of a beginner in C.
#include <stdio.h>
int main() {
const char arr[][20] = {"First Number : ", "Second Number : ", "Third Number : "};
int numbers[2]; // number list
int posNumbers[2]; // positive number list
int n = 0; // n for itinerating posNUmbers
for ( int i = 0 ; i <= 2; i++) {
printf("%s", arr[i]);
scanf("%i", &numbers[i]);
} // puts input in array
for ( int i = 0 ; i <= sizeof(numbers) / sizeof(numbers[0]) + 1 ; i++ ) {
if (numbers[i] > 0) {
posNumbers[n + 1] = numbers[i];
}
} // adds positive in array
if (sizeof(posNumbers) / sizeof(posNumbers[0]) + 1 > 1) {
printf("There are atleast 2 pos numbers, which are : \n");
for ( int i = 0; i <= sizeof(posNumbers) / sizeof(posNumbers[0]) + 1 ; i++) {
printf("%i", posNumbers[i]);
}
} else {
printf("THere are not enough positive numbers.");
}
}
Output : There are atleast 2 pos numbers, which are : 4419368778941968054388
You have several misconceptions about arrays and the use of sizeof that cause you to attempt to access values beyond the end of your numbers and posNumbers arrays that invokes Undefined Behavior1 in your code. You further invoke Undefined Behavior when you attempt to read from uninitialized elements in the posNumbers array.
In C, arrays are:
zero based. Meaning that an array of nelem elements has valid indexes of 0 <= index < nelem,
when looping over all elements in an array, you loop from i = 0; i < nelem; i++,
if you fail to initialize your arrays all zero and do not fill all elements and attempt to loop over all elements in your array, you invoke Undefined Behavior when you attempt to access the uninitialized element (lesson -- initialize all arrays to begin with),
when you use sizeof array / sizeof array[0], you get the total number of elements in the array, not the number of elements filled,
your loop over posNumbers ignores the fact that less than all elements can be filled invoking Undefined Behavior if you attempt to read from an uninitialized element of the array,
when filling less than all values in an array, simply keep a counter to track the number of elements filled, you have n declared already.
Additional points to consider:
avoid using MagicNumbers in your code and instead #define a constant. This helps avoid the problems you are having with 2,
above all learn you cannot use scanf() (or any user input function) correctly unless you check the return, especially where numeric conversions are involved. What if the user enters "four" instead of 4?
Putting it altogether, and making a few additional changes to your output calls, you can rewrite your code to avoid the problems above as:
#include <stdio.h>
#define NVALS 3 /* if you need a constant, #define one (or more) */
int main (void) {
/* an array of pointers to the string-literals is fine */
const char *arr[] = { "First Number : ",
"Second Number : ",
"Third Number : " };
int numbers[NVALS] = {0}, /* initialize all arrays */
posNumbers[NVALS] = {0},
n = 0;
/* loop NVALS times reading number input */
for (int i = 0 ; i < NVALS; i++) {
/* no conversion involved, fputs is fine for end-of-line control */
fputs (arr[i], stdout);
/* you can't use scanf correctly unless you CHECK THE RETURN
* to validate each conversion was successfully completed
*/
if (scanf("%i", &numbers[i]) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
/* compare if numbers[i] positive */
if (numbers[i] > 0) {
posNumbers[n++] = numbers[i];
}
}
if (n > 1) { /* check if at least two numbers positive */
puts ("\nThere are atleast 2 pos numbers, which are :");
for (int i = 0; i < n; i++) {
printf ("%i\n", posNumbers[i]);
}
}
else {
puts ("\nMust have at least two positive numbers.");
}
}
(note: a good compiler will convert printf ("const string"); to fputs ("const string", stdout); for you, but choosing fputs() over the variadic printf() when there are no conversions involved indicates you understand how to choose the proper tool for the job on your own)
Example Use/Output
If less than two positive integers:
$ ./bin/threeposnumbers
First Number : -10
Second Number : 0
Third Number : 4
Must have at least two positive numbers.
If the two positive numbers are provided:
$ /bin/threeposnumbers
First Number : -10
Second Number : 2
Third Number : 4
There are atleast 2 pos numbers, which are :
2
4
If all positive numbers are provided:
$ ./bin/threeposnumbers
First Number : 10
Second Number : 2
Third Number : 4
There are atleast 2 pos numbers, which are :
10
2
4
(if you are old enough, you will recall the special significance of those numbers for a specific soft-drink marketing campaign, hint: initials DP :)
Handling non-integer input:
$ ./bin/threeposnumbers
First Number : -10
Second Number : two
error: invalid integer input.
Let me know if you have further questions.
footnotes:
1.) See:
Undefined, unspecified and implementation-defined behavior and
What is indeterminate behavior in C++ ? How is it different from undefined behavior? and
Undefined behavior
You say you want to store 3 numbers but you are declaring your array size to be 2. If you want to store 3 numbers this code:
int numbers[2]; // number list
int posNumbers[2]; // positive number list
Should be
int numbers[3]; // number list
int posNumbers[3]; // positive number list
You are supposed to declare the array sizes as how big as you want them but you can only use up to size - 1 since indexes start from 0.
Also you should probably fix the things that #WeatherVane is stating in the comments.
Addendum on the answers: you can interleave then in a struct to make it clearer which variables go together. This can also reduce the number of times you repeat yourself.
You have: a) a fixed number of numbers to enter, and b) you are going to copy all the positive numbers to a second, possibly smaller, array. The simplest is to make an equal-size array and explicitly have the size. I would refactor the code as such,
#include <stdio.h>
int main(void) {
struct {
const char *title;
int number;
} arr[] = { { "First", 0 }, { "Second", 0 }, { "Third", 0 } };
struct {
size_t size;
int number[sizeof arr / sizeof *arr];
} positives;
const int arr_size = sizeof arr / sizeof arr[0];
// enter numbers
for ( size_t i = 0 ; i < arr_size; i++) {
printf("%s Number : ", arr[i].title);
if(scanf("%i", &arr[i].number) != 1) return 1;
}
// adds positive in array
positives.size = 0;
for ( size_t i = 0 ; i < arr_size ; i++ ) {
if (arr[i].number > 0) {
// bounded by arr_size
positives.number[positives.size++] = arr[i].number;
}
}
if (positives.size >= 2) {
printf("There are atleast 2 pos numbers, which are : \n");
for ( size_t i = 0; i < positives.size ; i++) {
printf("%i\n", positives.number[i]);
}
} else {
printf("THere are not enough positive numbers.\n");
}
}

C Programming: How to determine an exact match between 2 numbers

I am trying to find the exact match between two numbers and have my counter stop at the first instance when they are not a match. However the code I have written counts the entire string length of my numbers. Is there an alternative way to do this?
Since my counter is starting from the first decimal place and not 0. , it counts to 15 but should stop at 10.
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
int main(){
char str[100];
char buf[100];
double l,m,a,b;
int c,d,t,u,r,q;
int count =0;
l=59874.141715197809000;
m=59874.141715197817000;
a= (l - (int)l);
b= (m -(int)m);
sprintf(str,"%.15f",a);
sprintf(buf,"%.15f",b);
c = strlen(str);
d = strlen(buf);
for(t=3;t<c;t++){
for(u=3;u<d;u++){
if(str[t]==buf[u]){
count++;
break;
}
}
}
printf("matching decimal places = %d \n",count);
return 0;
}
First, when comparing two strings, you only need to iterate to the length of the smallest string if the two strings differ in length.. That is, if you want to count the amount of sequential character matches in a string.
For example:
A = 0.99997552
B = 0.9999753
would need one for loop to compare.. You would only iterate up to the length of B to determine that 6 decimals match. Why? Because going any further is irrelevant since none of the extra digits would exist in B. Iterating past the end of an array is undefined behaviour anyway.
In your case both buffers are the same length so no worries there, but again, the shorter string won't have the extra digits found in the longer string.. Hence: Iterate up to the smallest length.
The solution can be done as follows:
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
int main() {
//Create large enough buffer to hold 100 digits/characters..
char str[100] = {0};
char buf[100] = {0};
//Two doubles to be compared..
double l = 59874.141715197809000;
double m = 59874.141715197817000;
//Counter keeps track of matching digits..
int count = 0;
//Get rid of the base and keep only the decimals..
double a = (l - (int)l);
double b = (m - (int)m);
//Copy a maximum of 15 decimal places to `str` and `buf`
sprintf(str, "%.15f", a);
sprintf(buf,"%.15f", b);
//Get the length of both strings..
int c = strlen(str);
int d = strlen(buf);
//If C is smaller, iterate to length(c) else iterate to length(d).
for (int i = 2; i < (c < d ? c : d); ++i)
{
//If the two characters match, increment the count..
if (str[i] == buf[i])
{
++count;
}
}
//Print the amount of matching decimals..
printf("matching decimal places = %d \n", count);
return 0;
}
This may not be the answer, but do
if (number1 == number2)
{
// do something to stop it
}

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.

Correctly passing an array from a function

I have some code to generate an array of size [user_input] in a function called array_generator, using size of array from scanf in main(), and then filling it with the numbers 0 to user_input (0, 1, 2, 3, if user input is 4). The array fills correctly as printf prints
`The array contains the value 1`
`The array contains the value 2`
`The array contains the value 3`, etc.
However when I pass the array to main and printf the array values I get equal statements filled with garbage numbers. I'm also 90% sure I have been passing the arrays and pointers incorrectly (new to them).
The code is below:
#include <stdio.h>
int *array_generator(int number_songs);
int main(void)
{
int input;
int *p;
int i;
int x;
printf("Enter number of songs wanted in random playlist: ");
scanf("%d", &input);
p = array_generator(input);
x = *p;
for (i = 0; i < input; i++)
{
printf("The array contains the values %d\n", x);
}
return 0;
}
int *array_generator(int n)
{
int a[n];
int *p;
int i;
for (i = 0; i < n; i++)
{
a[i] = i;
printf("The array contains the values %d\n", i);
}
return p = &a[n];
}
One simple solution is to define an array which is bigger than the largest list of songs reasonably possible. For example, since you print every entry, more than a few hundred are not reasonable. On a modern computer space is abundant. You would have a define for the max size on top of the prog, or later in some header:
#define MAX_SONGLIST_LEN 1000
The array can be global, or it can be static inside the function. Let's make it static because you want the function to return the address.
The change is minimal. Just say
static int a[MAX_SONGLIST_LEN];
You may want to change the loop and check for the max length as well:
for (i = 0; i < input && i < MAX_SONGLIST_LEN; i++)
inside array_generator() and main(). You also may want to inform your users about the maximum, and catch numbers which are too large. (You don't do any error handling of user input anyway -- what happens if the user enters a letter instead of a number? Look into the return value of scanf().)
The static array's life time is the lifetime of the program. It will be initialized to all zeroes by the way. If you want to randomly initialize it look at the rand() function.
You are correct in that you are using pointers wrong. The code below preforms the function that you want...
#include <stdio.h>
void array_generator(int n, int arr[]) {
for (int i = 0; i < n; i++) {
arr[i] = i;//array values
//printf("The array contains the values %d\n", i);
}
}
int main() {
int input;
printf("Enter number of songs wanted in random playlist: ");
scanf("%d", &input);
int array[input];//declare array with length of input
array_generator(input, array);
for(int i=0; i<sizeof(array)/sizeof(array[0]); i++) {//input could also be used at the limit to the for loop
printf("%d", array[i]);
}
printf("\n");
return 0;
}
What you are doing is you are over complicating your code. The first thing you do is you create a function and try to make it return an array. This is not necessary. All you need to do is pass a pointer to the array and all edits to the array will be made on the same scope as the array was declared on.
You also mentioned that you want to find the size of an array. This can be done with array *a of any type and sizeof(a)/sizeof(a[0]). This works by returning the number of bytes used by the array divided by the number of bytes used by the first element in the array.
One more thing that you have that you don't need is x = *p;. when you do this, you are essentially doing this x=*p=array_gen(input);
More information on pointers in C can be found here.

Resources