Index manipulation of array in C - c

Begining with an ordered array
[1, 2, 3, 4, 5, 6, 8, 9, 10]
How would be the way to get every iteration the following results?
1 2 3 4 5 6 7 8 9 10
1 3 4 5 6 7 8 9 10 2
1 4 5 6 7 8 9 10 2 3
1 5 6 7 8 9 10 2 3 4
1 6 7 8 9 10 2 3 4 5
1 7 8 9 10 2 3 4 5 6
1 8 9 10 2 3 4 5 6 7
1 9 10 2 3 4 5 6 7 8
1 10 2 3 4 5 6 7 8 9
#include <stdio.h>
#define MAX 10
int a[MAX], i,j,cnt=2;
main (){
for (i=0; i<MAX; i++){
a[i]= i+1;
}
for (i=0; i<MAX; i++) {
printf ("%d ", a[i]);
}
printf ("\n");
for (j=0; j < MAX-2;j++){
a[0]=1;
for (i=1; i < MAX-1; i++){
if (a[i]%MAX != 0){
a[i]= a[i] + 1;
}else{
if (a[i]==10) {
//printf ("a[%d]: %d \t ** %d\n", i , a[i] ,cnt);
//a[i-1]= i;
a[i] = cnt;
}
}
}
for (i=0; i<MAX; i++) {
printf ("%d ", a[i]);
}
printf ("\n");
}
}
Now I almost get it but the last column is not right, What should I do?
1 2 3 4 5 6 7 8 9 10
1 3 4 5 6 7 8 9 10 10
1 4 5 6 7 8 9 10 2 10
1 5 6 7 8 9 10 2 3 10
1 6 7 8 9 10 2 3 4 10
1 7 8 9 10 2 3 4 5 10
1 8 9 10 2 3 4 5 6 10
1 9 10 2 3 4 5 6 7 10
1 10 2 3 4 5 6 7 8 10

C arrays are indexed from 0. So when you access elements from 1 to MAX, you are running off the end of the array.
Have your loops go from 0 to MAX-1. Customary way to write it is
for (i=0 ; i < MAX ; ++i)
...so anybody reading your code can immediately prove that the array index never equals MAX.

Well, at a minimum, arrays in C are zero based so you are writing past the end of the array. For an array declared int foo[MAX] valid elements are from foo[0]…foo[MAX-1]
Specifically a[MAX] might well reference the memory location that the variable i uses, causing the loop to reset when it attempt to overwrite a[MAX].
Either shift everything down by one, or declare your array MAX+1 and ignore the zero bit.
Oh, and you should not need to set a[1]=1; every time.

Related

Can anybody suggest me a better/shorter method for this pattern?

4 4 4 4 4 4 4
4 3 3 3 3 3 4
4 3 2 2 2 3 4
4 3 2 1 2 3 4
4 3 2 2 2 3 4
4 3 3 3 3 3 4
4 4 4 4 4 4 4
I want a shorter code or a more smarter code for this pattern.My code works fine but it is bit long.
MY CODE
#include <stdio.h>
int main()
{
int n,i,j;
scanf("%d",&n);
for(i=n;i>=1;i--)
{
for(j=n;j>i;j--)
{
printf("%d ",j);
}
for(j=1;j<(2*i)-1;j++)
{
printf("%d ",i);
}
for(j=i;j<=n;j++)
{
printf("%d ",j);
}
printf("\n");
}
for(i=2;i<=n;i++)
{
for(j=n;j>i;j--)
{
printf("%d ",j);
}
for(j=1;j<(2*i)-1;j++)
{
printf("%d ",i);
}
for(j=i;j<=n;j++)
{
printf("%d ",j);
}
printf("\n");
}
return 0;
}
How about like this:
#include <stdio.h>
#include <stdlib.h>
int max (int a, int b) {
return a > b ? a : b;
}
void pattern (int width) {
int count = width;
int digits = 1;
while (count /= 10)
++digits;
for (int line = 0; line < (2*width-1); ++line) {
for (int col = 0; col < (2*width-1); ++col) {
int val = max (abs (1+line-width)+1, abs (1+col-width)+1);
if (col > 0)
putc (' ', stdout);
printf ("%*d", digits, val);
}
puts ("");
}
}
int main (int argc, char* argv []) {
int width = argc > 1 ? atoi (argv [1]) : 4;
pattern (width);
}
The idea is to loop through all positions, calculate the distance to the middle position in both X and Y direction, and take the maximum of that.
I can suggest the following solution. Enjoy!:)
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
int main()
{
while ( 1 )
{
printf( "Enter a non-negative number (0 - exit): " );
int n;
if ( ( scanf( "%d", &n ) != 1 ) || ( n <= 0 ) ) break;
if ( INT_MAX / 2 < n )
{
n = INT_MAX / 2;
}
int width = 1;
for ( int tmp = n; tmp /= 10; ) ++width;
putchar( '\n' );
int m = 2 * n - 1;
for ( int i = 0; i < m; i++ )
{
for ( int j = 0; j < m; j++ )
{
int value1 = abs( n - i - 1 ) + 1;
int value2 = abs( n - j - 1 ) + 1;
printf( "%*d ", width, value1 < value2 ? value2 : value1 );
}
putchar( '\n' );
}
putchar( '\n' );
}
return 0;
}
The program output might look like
Enter a non-negative number (0 - exit): 10
10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
10 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10
10 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 9 10
10 9 8 7 7 7 7 7 7 7 7 7 7 7 7 7 8 9 10
10 9 8 7 6 6 6 6 6 6 6 6 6 6 6 7 8 9 10
10 9 8 7 6 5 5 5 5 5 5 5 5 5 6 7 8 9 10
10 9 8 7 6 5 4 4 4 4 4 4 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 3 3 3 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 2 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 2 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 3 3 3 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 4 4 4 4 4 4 5 6 7 8 9 10
10 9 8 7 6 5 5 5 5 5 5 5 5 5 6 7 8 9 10
10 9 8 7 6 6 6 6 6 6 6 6 6 6 6 7 8 9 10
10 9 8 7 7 7 7 7 7 7 7 7 7 7 7 7 8 9 10
10 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 9 10
10 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10
10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
Enter a non-negative number (0 - exit): 0
In fact there are used only two loops that output the pattern itself.
for ( int i = 0; i < m; i++ )
{
for ( int j = 0; j < m; j++ )
{
int value1 = abs( n - i - 1 ) + 1;
int value2 = abs( n - j - 1 ) + 1;
printf( "%*d ", width, value1 < value2 ? value2 : value1 );
}
putchar( '\n' );
}

fgets in a loop repeats data in the 2d array

I am trying to get my 9x9 grid of numbers from a file and store it in a 2D int array. For this, I wrote my code so that it uses fgets() from the file and then converts the char array values to an int and then stores it in that respective spot in the array.
While I thought it was working, when I printed out the array, I noticed how it has repeated values (from the previous row that it read) and it doesn't print out the full 9x9 grid. Here is what I mean:
int strIndex = 1; // Goes every odd to extract number
/* Need to do this for the whole grid */
for(int i = 0; i < 9; i++) {
fgets(str,19, f);
strIndex = 1;
// printf("%s\n", str);
for(int j = 0; j < 9; j++) {
// Since asci digits start at 48, subtracting gets you the num
grid[i][j] = (int) str[strIndex] - 48;
strIndex = strIndex + 2;
}
}
This is what I am supposed to be getting (basically whatever is in input.txt):
8 2 7 1 5 4 3 9 6
9 6 5 3 2 7 1 4 8
3 4 1 6 8 9 7 5 2
5 9 3 4 6 8 2 7 1
4 7 2 5 1 3 6 8 9
6 1 8 9 7 2 4 3 5
7 8 6 2 3 5 9 1 4
1 5 4 7 9 6 8 2 3
2 3 9 8 4 1 5 6 7
But this is what I am getting:
8 2 7 1 5 4 3 9 6
-38 2 7 1 5 4 3 9 6
9 6 5 3 2 7 1 4 8
-38 6 5 3 2 7 1 4 8
3 4 1 6 8 9 7 5 2
-38 4 1 6 8 9 7 5 2
5 9 3 4 6 8 2 7 1
-38 9 3 4 6 8 2 7 1
4 7 2 5 1 3 6 8 9
Am I using fgets() correctly? And what is -38? I can't seem to understand why that is being printed instead of the actual number. (For ex: Instead of 8 from grid[0][0], it prints -38 in grid[0][1]. In fgets, I made the space 19 because I noticed how fgets() also takes in whitespace, so that's why my strIndex is incrementing every 2.
Thanks
fgets(str,19, f)
That doesn't read the whole line. Your lines have 19 visible characters but there is a newline (\n) character at the end of each line. By reading only 19 characters you leave the newline for the next fgets. Hence every second fgets call will read a single newline character with the rest of the buffer retained from the previous line. The newline ascii value is 10 and that is where the -38 comes from since the code does str[strIndex] - 48.
So the fix would be to read 20 characters rather than 19. In fact, it wouldn't hurt to put an even larger buffer. Say 32 bytes. fgets will stop at the newline anyway.

C - Larger Output Than I have in File (Size Problem)

I have a file, with format:
Course - Grade Count - Grades
Programming 10 3 4 5 4 3 2 4 5 2 3
Mathematics 8 3 3 4 5 3 2 2 3
Physics 6 3 4 5 3 4 5
Design 6 5 4 5 3 2 4
Logistics 8 3 4 5 3 1 1 2 4
Ex: Course - Programming, Grade Count - 10 and Grades - 3 4 5 4 3 2 4 5 2 3
I already have
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define SIZE 70
int main(void)
{
char subject[SIZE];
int gradeCount;
int grades[SIZE];
FILE *fp = fopen("C:\\Project\\project.txt", "r"); //opening already created file
if (fp == NULL) {
perror("Error opening file");
return(-1);
}
for (int i = 0; i < SIZE; i++) {
fscanf(fp, "%s %d", &subject[i], &gradeCount);
printf("%s \n", &subject[i]);
//printf("%d \n", gradeCount);
for (int k = 0; k < gradeCount; k++)
{
fscanf(fp, "%d", &grades[k]);
// printf("%d \n" , grades[k]);
}
if (i == SIZE) {
break;
}
}
fclose(fp);
return 0;
}
I need to print out "Course", "Grade Count" and "Grades" without any problems, later on I need to make a search and so I need to separate them from each other, but that is not the case, now I will show you the outputs for all cases, when I output first "Subject/Course" then "Grade Count" and finally "Grades".
For Courses:
Programming
Mathematics
Physics
Design
Logistics
ogistics
gistics
istics
stics
tics
ics
cs
s
#
##
#
#
For Grade Count:
10
8
6
6
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
And for Grades:
3
4
5
4
3
2
4
5
2
3
3
3
4
5
3
2
2
3
3
4
5
3
4
5
5
4
5
3
2
4
3
4
5
3
1
1
2
4
3
4
5
3
1
1
2
4
3
4
5
3
1
1
2
4
3
4
5
3
1
1
2
4
3
4
5
3
1
1
2
4
3
4
5
3
1
1
2
4
3
4
5
3
1
1
2
4
3
4
5
3
1
1
2
4
3
4
5
3
1
1
2
4
3
4
5
3
1
1
2
4
3
4
5
3
1
1
2
4
3
4
5
3
1
1
2
4
3
4
5
3
1
1
2
4
3
4
5
3
1
1
2
4
3
4
5
3
1
1
2
4
3
4
5
3
1
1
2
4
In all cases, additional things are added to original stuff that should be printed out, I don't know where it comes from, I thought about pointers, but don't know much about them. Any suggestions?
Just need to print everything normally to normally search for everything (Courses, grade count and grades) later on.
You need to exit the loop early if it fails to read anything in. You can do that by checking the return value of fscanf. If the first call doesn't return 2, you know that it didn't read in 2 values and can break out of the loop.
You're also calling fscanf and printf incorrectly for dealing with a string. You are moving the starting point of where you read into/print from, which isn't needed and reduces the maximum space available to you.
Updated code looks something like this
for (int i = 0; i < SIZE; i++) {
if(fscanf(fp, "%s %d", subject, &gradeCount) != 2) {
break;
}
printf("%s ", subject);
//printf("%d \n", gradeCount);
for (int k = 0; k < gradeCount; k++)
{
fscanf(fp, "%d", &grades[k]);
// printf("%d" , grades[k]);
}
}

Improper Initialization of 2D Array in C

I am trying to construct a 2D array for an assignment. I've used a nested for loop to construct the 2D array using scanf():
int width;
int height;
scanf("%d %d",&width,&height);
int array[width][height];
for (int i=0;i<height;i++){
for (int j=0;j<width;j++){
scanf("%d",&array[i][j]);
}
}
However when I print the array, I can see that it has been constructed in a strange way, where all the numbers of the first line past a certain point are the first few numbers from the second line (instead of what they should be). The next lines after work fine.
Example:
Input:
6 2
1 3 5 7 9 1
2 4 6 8 0 2
3 4 2 0 1 3
The created array looks like this:
1 3 2 4 6 8 (<-- these last 4 numbers are the first 4 numbers of the second line)
2 4 6 8 0 2 (correct)
3 4 2 0 1 3 (correct)
Any ideas? Thanks a lot.
Your declaration of array
int array[width][height];
is wrong. The outer loop goes from 0 to height - 1, but array[i] can only go
from 0 to width - 1. The same applies for the inner loop. You swapped width
and height in the declaration of the array, it should be
int array[height][width];
Also note that for the matrix
1 3 5 7 9 1
2 4 6 8 0 2
3 4 2 0 1 3
the width is 6 and the height is 3, so the correct input should be
6 3
1 3 5 7 9 1
2 4 6 8 0 2
3 4 2 0 1 3
I compiled and run this code:
#include <stdio.h>
int main(void)
{
int width;
int height;
scanf("%d %d",&width,&height);
int array[height][width];
for (int i=0;i<height;i++){
for (int j=0;j<width;j++){
scanf("%d",&array[i][j]);
}
}
printf("----------------\n");
for (int i=0;i<height;i++){
for (int j=0;j<width;j++){
printf("%d ", array[i][j]);
}
printf("\n");
}
}
And the output is:
$ ./b
6 3
1 3 5 7 9 1
2 4 6 8 0 2
3 4 2 0 1 3
----------------
1 3 5 7 9 1
2 4 6 8 0 2
3 4 2 0 1 3
as you can see, now it's reading correctly. See https://ideone.com/OJjj0Y

Trick the randomizer in C

I want to get random numbers between 1 to 10.
It actually works, but when it's in a loop, I don't really get random numbers.
int randomNum;
srand ( (unsigned int)time(NULL) );
randomNum = rand() % 10;
I've been spending hours here and in google looking for a solution, but it looks like no one really solved it (or maybe I didn't search good enough).
The value we get from the randomizer depends on the seconds (not miliseconds or something else, like in other programming language) and that's why the numbers are not random.
In addition, I don't want to download a package for C because I run my code in the university labs, and they won't allow it.
Is there anyone with a creative solution for this problem? maybe some mathematic functions?
To illustrate Sidoh's answer.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main(int argc, char** argv)
{
int i;
srand ( (unsigned int)time(NULL) );
for (i = 0; i < 100; i++)
{
printf("%d ", 1 + (rand() % 10));
}
putchar('\n');
return 0;
}
This produced the following results for my one time seed using time( ).
7 10 2 4 4 4 2 1 7 7 10 4 3 10 2 9 6 9 2 9 7 10 4 1 1 8 2 4 8 1 2
4 2 3 9 5 8 1 7 4 9 8 10 1 8 1 1 5 1 4 5 7 3 9 10 3 6 1 9 3 4 10
8 5 2 7 2 2 9 10 5 9 8 4 1 7 7 2 3 7 5 8 6 10 8 5 4 3 7 2 8 2 1 7
7 5 5 10 6 5
Do not seed the random number generator more than once. Since your code probably runs all within the same second, every query to rand uses the same seed, so you'll get the same number every time.
Dave Newman provides a very good answer.
Alternatively, you could also try a pseudo random generator, for example
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main()
{
int a0; // this value will be our requirement
int mod = 11; //this is the limit (0 - mod-1), here 10
int a; // this stores the previous value of a0;
int i; // loop variable
int mul=25; //multiplicative factor
int add=3; // additive factor
int limit=100; // our limit
srand ( (unsigned int)time(NULL) ); // initialize the seed
a0 = rand() % mod;
for(i=0;i<limit;i++)
{
printf("%d\t",a0);
a = a0;
a0 = (a * mul + add) % mod;
}
putchar('\n');
return 0;
}
The output::
1st run::
2 10 4 3 1 8 0 6 7 9 2 10 4 3 1 8 0 6
7 9 2 10 4 3 1 8 0 6 7 9 2 10 4 3 1 8
0 6 7 9 2 10 4 3 1 8 0 6 7 9 2 10 4 3
1 8 0 6 7 9 2 10 4 3 1 8 0 6 7 9 2 10
4 3 1 8 0 6 7 9 2 10 4 3 1 8 0 6 7 9
2 10 4 3 1 8 0 6 7 9
2nd output::
9 2 10 4 3 1 8 0 6 7 9 2 10 4 3 1 8 0
6 7 9 2 10 4 3 1 8 0 6 7 9 2 10 4 3 1
8 0 6 7 9 2 10 4 3 1 8 0 6 7 9 2 10 4
3 1 8 0 6 7 9 2 10 4 3 1 8 0 6 7 9 2
10 4 3 1 8 0 6 7 9 2 10 4 3 1 8 0 6 7
9 2 10 4 3 1 8 0 6 7

Resources