Performing Operations on an Array - c

Ok, so I'm new to both programming and posting on this site and my question is kind of complicated, but I'm going to attempt to articulate my situation. I'm trying to write a code to read a file (a list of polar coordinates) of unknown size, store the values in an array, then perform a conversion and get out a new array with the converted data (technically I'm using this new array in a predesigned function to graph the data in C++, but this is not important since it's part of the assignment and certainly not the source of error).
I'm having 2 major issues, the first of which is the variable array size. In the code following, you can see that there's no constraint on my x and y arrays, so the loop goes on to convert values up to x[999] even if there's nothing in r[] beyond r[40]. I can constrain the size of my r and theta arrays because I can code to stop reading values when the fscanf function reaches the end of the file, but I don't know the analogy for my x and y arrays. (Also, I'd greatly appreciate it if someone could explain why my character array doesn't have this issue, even though it's defined to be up to 128 characters. It might give me the insight I need)
Secondly, the conversion doesn't quite match up. So when I print the converted values, the function converts them correctly, but stores the value converted from r[i] and theta[i] to x[i+1] and y [i+1]. I really have no idea what is causing this problem.
I certainly hope my issues make sense. Any help would be appreciated! If anything is unclear, please let me know and I'll do my best to explain. Thank you!
#include <stdio.h>
#include <math.h>
#define ARRAYSIZE 1000
#define FILENAMESIZE 128
float convertx(float r[], float theta[], int numPoints);
float converty(float r[], float theta[], int numPoints);
int cmain() {
int i;
float r[ARRAYSIZE], theta[ARRAYSIZE], x[ARRAYSIZE], y[ARRAYSIZE];
char filename[FILENAMESIZE];
FILE *InputFile;
printf("Type the data file name: ");
scanf("%s", filename);
InputFile = fopen(filename,"r");
if(InputFile == NULL){
printf("Error, could not open file: %s.\n",filename);
return 1;
}
for(i=0; i < ARRAYSIZE; i++){
if(fscanf(InputFile,"%f %f", &r[i], &theta[i]) == EOF) break;
printf("Value %d is %f\n",i+1,r[i]);
}
fclose(InputFile);
for(i=0; i < ARRAYSIZE; i++){
x[i] = convertx(r,theta,i);
printf("Value %d is %f\n",i+1,x[i]);
}
for(i=0; i < ARRAYSIZE; i++){
y[i] = converty(r,theta,i);
}
return 0;
}
float convertx(float r[], float theta[], int numPoints){
int i;
float x;
for(i=0; i < numPoints; i++)
x = r[i]*cos(theta[i]);
return x;
}
float converty(float r[], float theta[], int numPoints){
int i;
float y;
for(i=0; i < numPoints; i++)
y = r[i]*sin(theta[i]);
return y;
}
EDIT: Requested was a snippet of the input file. Here's the first few points (there are no commas in the file, just white space. Unfortunately, my formatting skills on this site are awful):
60, 3.9269875
60, 0.7853975
0, 0
1, 0.25
2, 0.5

For your first issue, the reason that your for-loop for r and theta stops at the end of the file is because you have a break; that exits the for-loop when you detect EOF. You don't have that in your x and y for-loops.
To fix that, instead of using your ARRAYSIZE constant, EDIT: { save the Final i value in your r and theta for-loops, it will be either the numbers of lines or +1, and use that for the end value in your x and y for-loop. Like this:
for(i=0; i < ARRAYSIZE; i++){
if(fscanf(InputFile,"%f %f", &r[i], &theta[i]) == EOF) {
int final = i;
break;
}
printf("Value %d is %f\n",i+1,r[i]);
}
fclose(InputFile);
for(i=0; i < final; i++){
x[i] = convertx(r,theta,i);
printf("Value %d is %f\n",i+1,x[i]);
}
I previously said you can use the size of the array for r or theta: for (i=0; i < r.size(); i++) {, but since you initialized its length to 1000 that won't work. }
For your 2nd issue: I think if you get rid of the for-loop in your convertx and converty functions, that will solve the problem. That's because only the last value of x or y calculated is returned, so your calculations from i=0 to i=(numPoints-2) are being thrown away.

Related

Imprecise average at run time

I am trying to solve a problem and I've run into a bit of an issue.
I have to find the running average of a series of numbers.
Example:
input 4 2 7
output 4 3 4.3333
Now here's the problem although I get the answer, it is not the precise answer.
Accepted Output: accuracy difference shown in the image
290.6666666667
385.4000000000
487.8333333333
477.4285714286
496.4444444444
...
523.8571166992
506.0454406738
495.3043518066
I can't find whats wrong. Some help would be highly appreciated.
#include<stdio.h>
main(){
int n;
printf("set:");
scanf("%d",&n);
float arr[n+1],resarr[n+1];
float sum=0;
for(int i=1; i<=n; i++){
scanf("%f",&arr[i]);
sum=arr[i]+sum;
float res= sum/(float)i;
resarr[i]=res;
}
int i=1;
while(i<=n) {
printf("%0.10f\n",resarr[i]);
i++;
}
return 0;
}
Here
for(int i=1; i<=n; i++){ }
you are trying to access out of bound array elements, this certainly causes undefined behavior as let's assume if n is 5 then you are accessing arr[5] also which doesn't exist.
C doesn't perform array boundary condition check, its programmer responsibility to not to access out of bound elements else it causes UB.
In C array index starts from 0 not from 1. So better start rotating loop from 0 to n. For e.g
for(int i=0; i<n; i++) {
scanf("%f",&arr[i]);
/* some code */
}
Code fails to achieve the desired accuracy as it is using float rather than double. #Some programmer dude
Typical float is precise to 1 part in 223. For printing to 0.0000000001, better to use double which is typically precise to 1 part in 253.
#include<stdio.h>
int main(void) {
//float arr[n + 1], resarr[n + 1];
//float sum = 0;
double arr[n + 1], resarr[n + 1];
double sum = 0;
...
// scanf("%f", &arr[i]);
scanf("%lf", &arr[i]);
...
// float res = sum / (float) i;
double res = sum / i; // cast not needed as `sum` is `double`
...
}
Iterating from 1 is not idiomatic in C. More common to iterate starting at 0.
size_t is best for array sizing and indexing. int may be too narrow. Of course with small arrays, it makes scant difference.
#include<stdio.h>
int main(void) {
printf("set:");
size_t n;
scanf("%zu", &n);
double arr[n], resarr[n];
double sum = 0;
for (size_t i = 0; i < n; i++) {
scanf("%lf", &arr[i]);
sum = arr[i] + sum;
double res = sum / (i+1);
resarr[i] = res;
}
for (size_t i = 0; i < n; i++) {
printf("%0.10f\n", resarr[i]);
}
return 0;
}
More robust code would check the input from the user it insure it is valid, allocate rather than use a VLA if n is allowed to be large, flush output before reading, etc.
Note that array arr[] is not needed, just a single double for the input and sum.

C - Passing a 3D arrays of chars to a function

I'm trying to write a program that analyzes a (3 x 4) matrix of strings provided by the user. Ultimately, it needs to output the longest string present in the matrix, along with that string's length.
My program seems to read the input correctly, as judged its success in echoing back the input strings, but it does not correctly output the longest word. I'm sure I'm committing some kind of pointer-related error when I pass the value of longest word, but I do not have any idea how to solve it.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define M 4
#define N 5
#define MAX_DIM 20
void findMAX(char matrice[N][M][MAX_DIM]) {
char maxr;
int index;
int i, j, it;
index = 0;
maxr = *(*(*(matrice+0)+0)+MAX_DIM);
for (i = 0; i < N-1; i++) {
for (j = 0; j < M-1; j++) {
if (index < strlen(matrice[i][j])) {
index = strlen(matrice[i][j]);
// I save the longer line's value
it = i;
// I save the maximum's value
maxr = *(*(*(matrice+i)+j)+MAX_DIM);
}
}
}
printf ("The MAX is: -/%s/- and it's long: -/%d/- \n", maxr, index);
printf ("It is content in the: %d line, which is: \n", it);
for (j = 0; j < N-1; j++) {
printf("%s ", matrice[it][j]);
}
}
void leggi(char matrice[N][M][MAX_DIM]) {
int i, j;
for (i = 0; i < N-1; i++) {
for (j = 0; j < M-1; j++) {
printf ("Insert the element matrix [%d][%d]: ", i, j);
scanf ("%s", matrice[i][j]);
fflush(stdin);
}
}
}
void stampa(char matrice[N][M][MAX_DIM]) {
int i, j;
printf("\n(4 x 3) MATRIX\n");
for (i = 0; i < N-1; i++) {
for (j = 0; j < M-1; j++) {
printf("%s ", matrice[i][j]);
}
printf("\n\n");
}
}
int main(int argc, char *argv[]) {
char matrix[N][M][MAX_DIM]; //Matrix of N*M strings, which are long MAX_DIM
printf("************************************************\n");
printf("** FIND THE LINE WITH THE MAXIMUM ELEMENT **\n");
printf("** IN A (4 x 3) MATRIX **\n");
printf("************************************************\n");
printf ("Matrix Reading & Printing\n");
leggi (matrix);
stampa (matrix);
findMAX(matrix);
return 0;
}
First of all to address some misconceptions conveyed by another answer, consider your 3D array declared as
char matrix[N][M][MAX_DIM];
, where N, M, and MAX_DIM are macros expanding to integer constants.
This is an ordinary array (not a variable-length array).
If you want to pass this array to a function, it is perfectly acceptable to declare the corresponding function parameter exactly the same way as you've declared the array, as indeed you do:
void findMAX(char matrice[N][M][MAX_DIM])
But it is true that what is actually passed is not the array itself, but a pointer to its first element (by which all other elements can also be accessed. In C, multidimensional arrays are arrays of arrays, so the first element of a three-dimensional array is a two-dimensional array. In any case, that function declaration is equivalent to both of these:
void findMAX(char (*matrice)[M][MAX_DIM])
void findMAX(char matrice[][M][MAX_DIM])
Note in particular that the first dimension is not conveyed. Of those three equivalent forms, I find the last clearest in most cases.
It is quite odd, though, the way you access array elements in your findMAX() function. Here is the prototypical example of what you do:
maxr = *(*(*(matrice+i)+j)+MAX_DIM);
But what an ugly and confusing expression that is, especially compared to this guaranteed-equivalent one:
maxr = matrice[i][j][MAX_DIM];
Looking at that however, and it how you are using it, I find that although the assignment is type-correct, you are probably using the wrong type. maxr holds a single char. If you mean it to somehow capture the value of a whole string, then you need to declare it either as an array (into which you will copy strings' contents as needed), or as a pointer that you will set to point to the string of interest. The latter approach is more efficient, and I see nothing to recommend the former for your particular usage.
Thus, I think you want
char *maxr;
... and later ...
maxr = matrice[0][0];
... and ...
maxr = matrice[i][j];
That sort of usage should be familiar to you from, for example, your function stampo(); the primary difference is that now you're assigning the expression to a variable instead of passing it directly to a function.
And it turns out that changing maxr's type that way will correct the real problem here, which #AnttiHaapala already pointed out in comments: this function call ...
printf ("The MAX is: -/%s/- and it's long: -/%d/- \n", maxr, index);
requires the second argument (maxr) to be a pointer to a null-terminated array of char in order to correspond to the %s directive in the format string. Before, you were passing a single char instead, but with this correction you should get mostly the expected result.
You will probably, however, see at least one additional anomaly. You final loop in that function has the wrong bound. You are iterating with j, which is used as an index for the second dimension of your array. That dimension's extent is M, but the loop runs to N - 1.
Finally, I should observe that it's odd that you allocate space for a 5 x 4 array (of char arrays) and then ignore the last row and column. But that's merely wasteful, not wrong.
Try something like this:
void findMAX(char matrice[N][M][MAX_DIM]){
// char maxr
char maxr[MAX_DIM];
int index;
int i, j, it;
index = 0;
// maxr = *(*(*(matrice+0)+0)+MAX_DIM);
strncpy(maxr, *(*(matrice+0)+0), MAX_DIM);
for (i = 0; i < N-1; i++)
{
for (j = 0; j < M-1; j++)
{
if (index < strlen(matrice[i][j]))
{
index = strlen(matrice[i][j]);
it = i;
// maxr = *(*(*(matrice+i)+j)+MAX_DIM);
strncpy(maxr, *(*(matrice+i)+j), MAX_DIM);
}
}
}
printf ("The MAX is: -/%s/- and it's long: -/%d/- \n", maxr, index);
printf ("It is content in the: %d line, which is: \n", it);
// for (j = 0; j < N-1; j++){
for (j = 0; j < M-1; j++){
printf("%s ", matrice[it][j]);
}
}
It's possible to pass multi-dimensional arrays to C functions if the size of the minor dimensions is known at compile time. However the syntax is unacceptable
void foo( int (*array2d)[6] )
Often array dimensions aren't known at compile time and it is necessary to create a flat array and access via
array2D[y*width+x]
Generally it's easier just to use this method even if array dimensions are known.
To clarify in response to a comment, C99 allows passing of variable size arrays using the more intuitive syntax. However the standard isn't supported by Microsoft's Visual C++ compiler, which means that you can't use it for many practical purposes.

How do you break an array in to little arrays of a fixed size? (in C)

I was trying to do an exercise in Hacker Rank but found that my code(which is below) is too linear. To make it better I want to know if it is possible to break an array in to little arrays of a fixed size to complete this exercise.
The Exersise on HackerRank
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
int N, M, Y, X;
scanf("%d %d %d %d", &N, &M, &Y, &X);
int max = 0;
int total = 0;
int data[N][M];
for(int i = 0; i < N; i++)
{
for(int j = 0; j < M; j++)
{
scanf("%d",&(data[i][j]));
}
}
for(int i = 0; i < N; i++)
{
for(int j = 0; j < M; j++)
{
total = 0;
for(int l = 0; (l < Y) && (i + Y) <= N; l++)
{
for(int k = 0; (k < X) && (j + X <= M); k++)
{
total += data[i+l][j+k];
}
if(total > max)
max = total;
}
}
}
printf("%d",max);
return 0;
}
While "breaking" it into pieces implies that we'd be moving things around in memory, you may be able to "view" the array in such a way that is equivalent.
In a very real sense the name of the array is simply a pointer to the first element. When you dereference an element of the array an array mapping function is used to perform pointer arithmetic so that the correct element can be located. This is necessary because C arrays do not natively have any pointer information within them to identify elements.
The nature of how arrays are stored, however, can be leveraged by you to treat the data as arbitrary arrays of whatever size you'd like. For example, if we had:
int integers[] = {1,2,3,4,5,6,7,8,9,10};
you could view this as a single array:
for(i=0;i!=10;i++){ printf("%d\n", integers[i]); }
But starting with the above array you could also do this:
int *iArray1, *iArray2;
iArray1 = integers;
iArray2 = integers + (5 * sizeof(int));
for(i=0;i!=5;i++){ printf("%d - %d\n", iArray1[i], iArray2[i]);}
In this way we are choosing to view the data as two 5 term arrays.
The problem is not in the linear solution. The main problem is in your algorithm complexity. As it's written it's O(N^4). Also I think your solution is not correct since:
The ceulluar tower can cover a regtangular area of Y rows and X columns.
It does not mean exactly Y rows and X columns IMHO you could find a solution where the are dimension is less than X, Y.
The problems like that are solvable in reasonable time using dynamic programming. Try to optimize your program using dynamic programming to O(N^2).

C: Program crashes before completing for loop

Hello Stackoverflow crew. I'm a very amateur C programmer and I'm working on a program that reads some input about wedding gifts, and then outputs information that includes the maximum gift value, the minimum gift value, the total average of the gift values, and the average of the gifts that were valued at x > 0. I've finished writing everything, but the program always seems to crash after the first loop. I've been looking at it for the past few hours, so I'm having issues finding what the error might be. Here is the code I have:
#include <stdio.h>
#include <stdlib.h>
int main() {
//Opens the file and creats a pointer for it.
FILE *ifp;
ifp = fopen("gifts.txt", "r");
//Declares the variables
int i, j, k, l, m, n, o, p, q, x, y;
int gift_sets, num_gifts, prices, max_value, max, avg_val, no_zero;
//Scans the file and assigns the first line to variable "gift_sets"
fscanf(ifp, "%d", &gift_sets);
//Begins a for loop that repeats based on the value of gift_sets
for (i = 0; i < gift_sets; i++) {
printf("Wedding Gifts #%d\n", i + 1);
printf("Gift Value\t Number of Gifts\n");
printf("----------\t ---------------\n");
//Scans the price values into the array prices[num_gifts]
fscanf(ifp, "%d", &num_gifts);
int prices[num_gifts];
//Creates a loop through the prices array
for (j = 0; j < num_gifts; j++){
fscanf(ifp, "%d", &prices[j]);
}
//Declares a frequency array
int freq[max + 1];
for (k = 0; k <= max; k++) {
freq[k] = 0;
}
for (l = 0; l < num_gifts; l++) {
freq[prices[l]]++;
}
for (m = 0; m < max + 1; m++) {
if (freq[m] > 0){
printf("%d\t%d",m, freq[m]);
}
}
printf("\n");
//Zeroes the variable "max_val."
int max_val = prices[0];
//Loops through the array to find the maximum gift value.
for (n = 0; n < num_gifts; n++){
if (prices[n] > max_value)
max_value = prices[n];
}
// Zeroes "min_val."
int min_val = prices[0];
//Finds the lowest value within the array.
for(o = 0; o < num_gifts; o++){
if(prices[o] !=0){
if(prices[o] < min_val){
min_val = prices[o];
}
}
}
//Calculates the total number of gifts.
double sum_gifts = 0;
for(p = 0; p < num_gifts; p++){
sum_gifts = sum_gifts + prices[p];
}
//Calculates the average value of all the gifts.
avg_val = (sum_gifts / num_gifts);
//find non zero average
double x = 0;
int y = 0;
for(q = 0; q < num_gifts; q++){
if (prices[q] != 0){
x += prices[q];
y++;
}
}
//Calculates the average value of the gifts, excluding the gifts valued zero.
int no_zero = x / y;
//Prints the maximum gift value.
printf("The maximum gift value is: $%d", max_value);
printf("\n");
//Prints the minimum gift value.
printf("The minimum gift value is: $%d\n", min_val);
//Prints the average of all the gifts.
printf("The average of all gifts was $%.2lf\n",avg_val);
//Prints the no zero average value of the gifts.
printf("The average of all non-zero gifts was $%.2lf",no_zero);
printf("\n\n\n");
}
return 0;
}
Thanks in advance for the help guys. As always, it's much appreciated.
EDIT: To further elaborate, the "crash" is a windows error "gifts.exe has stopped working" when executing the program. It does say at the bottom of the window that "Process returned -1073741819 <0xC0000005>"
When you declare the array with the num_gifts variable, it generates assembly instructions which allocate enough space on the stack to hold num_gifts integers. It does this at compile-time. Normally this wouldn't compile, but depending on the behavior of the ms c compiler, it could compile and assume whatever value is put in num_gifts by default (maybe 0, maybe something else) is the length. When you access it, it's possible that you're trying to access an array with zero elements, which could cause an access violation.
I'll tell you one thing you should do, straight away.
Check the return values from fscanf and its brethren. If, for some reason the scan fails, this will return less than you expect (it returns the number of items successfully scanned).
In that case, your data file is not what your code expects.
You should also be checking whether ifp is NULL - that could be the cause here since you blindly use it regardless.
One thing you'll find in IDEs is that you may not be in the directory you think you're in (specifically the one where gifts.txt is).
And, on top of that, max ill be set to an arbitrary value, so that int freq[max+1]; will give you an array of indeterminate size. If that size is less than the largest price, you'll be modifying memory beyond the end of the array with:
freq[prices[l]]++;
That's a definite no-no, "undefined behaviour" territory.
At least at first glance, it looks like you haven't initialized max before you (try to) use it to define the freq array.

Deshuffle text with C

I wanted to get an opinion here. Would it be possible to write a C program that deshuffles a text file? What do I mean by that? Say I have the following data in a textfile:
1 X
4 T
3 Z
2 L
And I wanted to deshuffle it and output another file as so:
1 X
2 L
3 Z
4 T
Such that all of the data following the number is preserved with the actual index number. Do know that I have 40,500 shuffled entities, so that should probably be taken into account since that could take a long time if the program needs to loop through all of the entities for each entity...And I only used letters for representation. The actual data files don't have letters, but rather have floats. Sorry if this causes any confusion
So, bottom line, would this be possible with C? And if so, could I get a hint at where to start? I could obviously input all of the textfile data into an array dat[][], but how should I deshuffle it then?
Thanks!
Amit
Look up qsort, its part of stdlib.
I'd just use sort -n instead of writing a program.
If you know the largest index in the file and there are no holes (i.e. all indices are present), you can create an array of that size, then as you read each line of the file, put the data into the correct location in the array. When you're done reading the file, your array will have all the elements in the correct order.
You can build a vector< pair<int,float[4]> > and just sort it using STL.
Just noticed a c tag.... But C idea is about the same:
Build an array with the data:
struct pair
{
int idx;
float val[4];
}
pair *data;
And then just sort it.
For those interested, I ended up using a series of loops to write this program, the code is show below. The only downside of it is that if my nrow variable is equal to 40,500, this program can take as long as 30 mins to run on a 3GHz dual core computer. I'm sure there are ways to optimize it, though at least it does what I want...for now.
Here's the code:
#include "stdlib.h"
#include "stdio.h"
// Deshuffle the output files of the bond/swap mode
int main(int argc, char* argv[])
{
if (argc < 4) {
printf("\ndeshuffle usage: [number of chains] [number of atoms] [.dat file] \n");
exit(1);
}
int i,j,k,l;
int nch = atoi( argv[1] );
int ns = atoi( argv[2] );
double **in_dat, **s_dat, dm1;
int nrow = ns*nch;
in_dat = (double**) calloc(nrow, sizeof(double*));
s_dat = (double**) calloc(nrow, sizeof(double*));
for (i=0; i<nrow; i++) {
in_dat[i] = (double*) calloc(6, sizeof(double));
s_dat[i] = (double*) calloc(6, sizeof(double));
for (j=0; j<6; j++)
in_dat[i][j] = 0.0;
s_dat[i][j] = 0.0;
}
// store input data into 2D array in_dat
FILE *inp;
inp = fopen( argv[3], "r" );
for (i=0; i<nrow; i++) {
for (j=0; j<6; j++) {
fscanf(inp, "%lf", &dm1);
in_dat[i][j] = dm1;
}
}
fclose(inp);
// Sort data in s_dat based on comparison with in_dat
k=0;
while (k < (nrow)) {
for (i=0; i<nrow; i++) {
for (l=0; l<nrow; l++) {
if (in_dat[l][0] == (k+1)) {
for (j=0; j<6; j++) {
s_dat[i][j] = in_dat[l][j];
}
k++;
break;
}
}
}
}
// Write sorted data to file
FILE *otp;
otp = fopen("results.out", "w");
for (i=0; i<nrow; i++) {
for (j=0; j<6; j++) {
fprintf(otp, "%lf \t", s_dat[i][j]);
if (j==5)
fprintf(otp, "\n");
}
}
fclose(otp);
printf("\n Done. \n\n");
return 0;
}

Resources