Hey all I am trying to store a matrix in an array of chars and then print it out.
My code that I have written:
#include<stdio.h>
#include<stdlib.h>
int main() {
int i;
int j;
int row=0;
int col=0;
int temp=0;
char c;
int array[3][2] = {{}};
while((c=getchar()) !=EOF && c!=10){
if((c==getchar()) == '\n'){
array[col++][row];
break;
}
array[col][row++]=c;
}
for(i=0; i<=2; i++){
for(j=0; j<=3; j++){
printf("%c ", array[i][j]);
}
printf("\n");
}
}
Using a text file such as:
1 2 3 4
5 6 7 8
9 1 2 3
I would like to be able to print that back out to the user, however what my code outputs is:
1 2 3 4
3 4 5 6
5 6 7 8
I cannot figure out what is wrong with my code, some how I am off an iteration in one of my loops, or it has something to do with not handling new lines properly. Thanks!
A few problems that I can see are:
As user3386109 mentioned in the comments, your array should be array[3][4] to match the input file.
The line array[col++][row]; does nothing but increment col, and then uselessly indexes the array and throws away the value. You can do the same thing with just col++;. However, you're not even using col at any later point in the code, so really you don't even need that. The break; all by itself does what you need. Which leads me to...
You're not populating the array like you think you are. You're incrementing col and then immediately breaking out of the loop. So how does the entire array ever get populated? Just by pure luck. As it turns out with your array declared as array[3][4], the array access array[0][4] (which isn't even technically supposed to exist) is equivalent to array[1][0]. This is because all multidimensional arrays (in C and just about any other language) are laid out in memory as flat arrays, because memory itself uses linear addressing. In C, this flattening of multidimensional arrays is done in so-called Row-major order, meaning that as you traverse the raw memory from first address to last, the corresponding multidimensional indices (i,j,k,...z, or in your case just i,j) increment in such a way that the last index will change the fastest. So, not only does col never get incremented except for right before you break out of the loop, but row never gets reset to 0, which means you're storing values in array[0][0], array[0][1], ... array[0][11], not array[0][0] .. array[0][3], array[1][0] .. array[1][3], array[2][0] .. array[2][3] as you were expecting. It was just luck that, thanks to row-major ordering, these two sets of indices were actually equivalent (and C doesn't do array bounds checking for you because it assumes you're doing it yourself).
This is just personal preference, but you will usually see arrays referenced as array[row][col], not array[col][row]. But like I said, that's just preference. If it's easier for you to visualize it as [col][row], then by all means do it that way. Just make sure you do it consistently and don't accidentally switch gears midway through your code to doing [row][col].
Your code will break and only print out part of the matrix if you accidentally put a trailing space at the end of one of your rows of numbers, because of the weird way you're checking for the end of input (doing a second getchar after each initial getchar and checking to see if the second character is \n). This method isn't wrong per se, in the sense that it will work, but it's not very robust and relies on your input data being precisely formatted and containing no trailing spaces. Anyone who has ever spent hours trying to figure out why their Makefile didn't work, only to find out that it was because they had leading spaces instead of tabs can attest to the fact that those kinds of errors can be extremely time-consuming and frustrating to track down. Precisely formatted input data is always a good thing, but your code shouldn't break in unexpected an non-obvious ways (such as only printing out half of a matrix) when it doesn't get perfect input. Edit: It only occurred to me later on that you were actually intending to do two mutually exclusive things here: increment col for the next line of input, and break out of the loop after having (presumably) detected the end of input. You need to figure out which thing you're doing here, although thanks to item #3, your code actually (and oddly) works just by taking user3386109's advice and changing array[3][2] to array[3][4].
I can only assume you used <= 2 and <= 3 in your for loops instead of < 3 and < 4, respectively, because you prefer doing it that way. That's fine, but it generally makes for easier-to-read code if your for loop conditions match up with your array dimensions. Just speculating here, but perhaps that's why you had array[3][2] when you really meant array[3][4].
Related
I'm totally new here but I heard a lot about this site and now that I've been accepted for a 7 months software development 'bootcamp' I'm sharpening my C knowledge for an upcoming test.
I've been assigned a question on a test that I've passed already, but I did not finish that question and it bothers me quite a lot.
The question was a task to write a program in C that moves a character (char) array's cells by 1 to the left (it doesn't quite matter in which direction for me, but the question specified left). And I also took upon myself NOT to use a temporary array/stack or any other structure to hold the entire array data during execution.
So a 'string' or array of chars containing '0' '1' '2' 'A' 'B' 'C' will become
'1' '2' 'A' 'B' 'C' '0' after using the function once.
Writing this was no problem, I believe I ended up with something similar to:
void ArrayCharMoveLeft(char arr[], int arrsize, int times) {
int i;
for (i = 0; i <= arrsize ; i++) {
ArraySwap2CellsChar(arr, i, i+1);
}
}
As you can see the function is somewhat modular since it allows to input how many times the cells need to move or shift to the left. I did not implement it, but that was the idea.
As far as I know there are 3 ways to make this:
Loop ArrayCharMoveLeft times times. This feels instinctively inefficient.
Use recursion in ArrayCharMoveLeft. This should resemble the first solution, but I'm not 100% sure on how to implement this.
This is the way I'm trying to figure out: No loop within loop, no recursion, no temporary array, the program will know how to move the cells x times to the left/right without any issues.
The problem is that after swapping say N times of cells in the array, the remaining array size - times are sometimes not organized. For example:
Using ArrayCharMoveLeft with 3 as times with our given array mentioned above will yield
ABC021 instead of the expected value of ABC012.
I've run the following function for this:
int i;
char* lastcell;
if (!(times % arrsize))
{
printf("Nothing to move!\n");
return;
}
times = times % arrsize;
// Input checking. in case user inputs multiples of the array size, auto reduce to array size reminder
for (i = 0; i < arrsize-times; i++) {
printf("I = %d ", i);
PrintArray(arr, arrsize);
ArraySwap2CellsChar(arr, i, i+times);
}
As you can see the for runs from 0 to array size - times. If this function is used, say with an array containing 14 chars. Then using times = 5 will make the for run from 0 to 9, so cells 10 - 14 are NOT in order (but the rest are).
The worst thing about this is that the remaining cells always maintain the sequence, but at different position. Meaning instead of 0123 they could be 3012 or 2301... etc.
I've run different arrays on different times values and didn't find a particular pattern such as "if remaining cells = 3 then use ArrayCharMoveLeft on remaining cells with times = 1).
It always seem to be 1 out of 2 options: the remaining cells are in order, or shifted with different values. It seems to be something similar to this:
times shift+direction to allign
1 0
2 0
3 0
4 1R
5 3R
6 5R
7 3R
8 1R
the numbers change with different times and arrays. Anyone got an idea for this?
even if you use recursion or loops within loops, I'd like to hear a possible solution. Only firm rule for this is not to use a temporary array.
Thanks in advance!
If irrespective of efficiency or simplicity for the purpose of studying you want to use only exchanges of two array elements with ArraySwap2CellsChar, you can keep your loop with some adjustment. As you noted, the given for (i = 0; i < arrsize-times; i++) loop leaves the last times elements out of place. In order to correctly place all elements, the loop condition has to be i < arrsize-1 (one less suffices because if every element but the last is correct, the last one must be right, too). Of course when i runs nearly up to arrsize, i+times can't be kept as the other swap index; instead, the correct index j of the element which is to be put at index i has to be computed. This computation turns out somewhat tricky, due to the element having been swapped already from its original place. Here's a modified variant of your loop:
for (i = 0; i < arrsize-1; i++)
{
printf("i = %d ", i);
int j = i+times;
while (arrsize <= j) j %= arrsize, j += (i-j+times-1)/times*times;
printf("j = %d ", j);
PrintArray(arr, arrsize);
ArraySwap2CellsChar(arr, i, j);
}
Use standard library functions memcpy, memmove, etc as they are very optimized for your platform.
Use the correct type for sizes - size_t not int
char *ArrayCharMoveLeft(char *arr, const size_t arrsize, size_t ntimes)
{
ntimes %= arrsize;
if(ntimes)
{
char temp[ntimes];
memcpy(temp, arr, ntimes);
memmove(arr, arr + ntimes, arrsize - ntimes);
memcpy(arr + arrsize - ntimes, temp, ntimes);
}
return arr;
}
But you want it without the temporary array (more memory efficient, very bad performance-wise):
char *ArrayCharMoveLeft(char *arr, size_t arrsize, size_t ntimes)
{
ntimes %= arrsize;
while(ntimes--)
{
char temp = arr[0];
memmove(arr, arr + 1, arrsize - 1);
arr[arrsize -1] = temp;
}
return arr;
}
https://godbolt.org/z/od68dKTWq
https://godbolt.org/z/noah9zdYY
Disclaimer: I'm not sure if it's common to share a full working code here or not, since this is literally my first question asked here, so I'll refrain from doing so assuming the idea is answering specific questions, and not providing an example solution for grabs (which might defeat the purpose of studying and exploring C). This argument is backed by the fact that this specific task is derived from a programing test used by a programing course and it's purpose is to filter out applicants who aren't fit for intense 7 months training in software development. If you still wish to see my code, message me privately.
So, with a great amount of help from #Armali I'm happy to announce the question is answered! Together we came up with a function that takes an array of characters in C (string), and without using any previously written libraries (such as strings.h), or even a temporary array, it rotates all the cells in the array N times to the left.
Example: using ArrayCharMoveLeft() on the following array with N = 5:
Original array: 0123456789ABCDEF
Updated array: 56789ABCDEF01234
As you can see the first cell (0) is now the sixth cell (5), the 2nd cell is the 7th cell and so on. So each cell was moved to the left 5 times. The first 5 cells 'overflow' to the end of the array and now appear as the Last 5 cells, while maintaining their order.
The function works with various array lengths and N values.
This is not any sort of achievement, but rather an attempt to execute the task with as little variables as possible (only 4 ints, besides the char array, also counting the sub function used to swap the cells).
It was achieved using a nested loop so by no means its efficient runtime-wise, just memory wise, while still being self-coded functions, with no external libraries used (except stdio.h).
Refer to Armali's posted solution, it should get you the answer for this question.
I have an array called allnumbersarray and I need to remove the duplicates of the array and store them in another called uniqueprimes. The allnumbersarray is composed of prime numbers. When I try to use an if - else if statement, the output gets jumbled and a lot of the elements turn to 0 and aren't sorted anymore. Here is what I've tried, not sure what to change:
int temp[], temp2[];
int removeDuplicates()
{
int n, j =0;
temp[n];
temp2[n];
// Start traversing elements
for (int i=0; i<n-1; i++){
// If current element is not equal
// to next element then store that
// current element
if (allnumbersarray[i] != allnumbersarray[i+1]){
temp[j++] = allnumbersarray[i];
}
else if(allnumbersarray[i] == allnumbersarray[i+1])
temp2[j++] = allnumbersarray[i];
}
// Store the last element as whether
// it is unique or repeated, it hasn't
// stored previously
temp[j++] = allnumbersarray[n-1];
// Modify original array
for (int i=0; i<j; i++){
allnumbersarray[i] = temp[i];
}
printf("\n\nprimes array with duplicates removed:\n");
for (int i = 0; i < j; i++)
printf("%d\n", allnumbersarray[i]);
return j;
}
You have not created an MCVE (Minimal, Complete, Verifiable Example — which is a problem. Some of the following criticism might be irrelevant if the code presented was an MCVE.
There are too many global variables in the code fragment (temp, temp2), and also not enough (you've not shown how allnumbersarray[] is defined). Use arguments to functions to pass data.
You say you have:
int temp[], temp2[];
int removeDuplicates()
{
int n, j =0;
temp[n];
temp2[n];
for (int i=0; i<n-1; i++){
You don't show where temp and temp2 are defined with a size — this line should have an extern in front of it. (I'm not sure why you don't use temp1 and temp2, but that's a common idiosyncrasy.)
The function isn't defined with a prototype; use int removeDuplicates(void) to indicate that it should be called with no arguments. As it stands, code in the same file could write removeDuplicates(3.14, "astronomy"); and the compiler is not obliged to spot the discrepancy because the function definition does not give a prototype for the function.
You have an uninitialized variable n inside the function; it's value is indeterminate. For some unexplained reason, you have temp[n]; and temp2[n];, statements which read from indeterminate locations in (or, more likely, outside) the dubiously declared arrays. The compiler might remove these references, if you're lucky, since they don't affect the computation. But they are misguided twice — once because they do nothing and once because they use the uninitialized variable to index the arrays.
You then use this uninitialized variable n as a bound for your main for loop. This is not going to end happily. You never use the values carefully stored in temp2.
I think you need to redesign your function thoroughly. For example, you might use:
int removeDuplicates(int *n_values, int *values, int *dups)
{
where *n_values is the number of entries in the source array (values), which becomes one of the output arrays. It's passed by reference so you can identify to the calling function how many unique entries there are in the values array after the duplicate removal is complete (use int n = *n_values; near the start, and *n_values = …new size…; at the end). The dups array is equivalent to your temp2. It is assumed to be 'big enough' (which is actually a dangerous assumption). The function will directly return the number of entries in dups, like the current function would if it were written correctly.
Somewhere along the line, with the current scheme, you have to copy the unique values from the source array (values) into spare space, simply so you can copy it back later. A better algorithm steps through the source array with two indexes, the current read position and the current write position. When you find an adjacent duplicate, you increment the read position without incrementing the write position. This means you end up not needing the temp array at all.
You also same the code 'removes duplicates' but the algorithm only looks for adjacent duplicates. If you had an input list (int[]){ 2, 3, 3, 5, 7, 7, 3, 11, 11, 13, 17, 19, 11 } (that's a compound literal), your code would not spot the third 3 nor the third 11. It isn't clear whether that's a problem — it may be that the duplicates can only occur adjacent to each other, in which case you don't have to be as complicated in your analysis as you do if duplicates need not be adjacent.
This at least gives you some things to think about.
Next time, please make sure you post a more complete MCVE; what you've presented is too minimal for comfort. And avoid global variables like the plague they are. Most functions should have parameters to identify what they're going to work on.
I have to allocate a dynamic array and i know how many columns there will be on the array but i don't know how many rows, all i have is a number on a .txt file. I have tried the following code but i am not sure it will work:
int x = (int)fgetc(file)-48;
Since the ascii value of 0 is 48, i assumned that i needed to cast the character read from the file in order to be able to use it as my rows number.
I assume i should be able to allocate the array the 2D array as it follows:
m = (int **)malloc(x*sizeof(int*));
for (i=0;i<x;i++)
{
m[i] = (int*)malloc(10*sizeof(int));
}
Am i correct? Any help will be highly apretiated.
You can design a list and dynamically insert your rows.
First off fgetc() returns an integer, so casting it as an int will do nothing. Second you're only reading in one integer at a time with fgetc() so you will have a 1 digit number in x.
Your array allocation looks correct, but you can also allocate the columns as an array of int * on the stack and then allocate the rows dynamically as m[i] = (int*)malloc(x*sizeof(int)); from i = 0->9
Do I understand correctly that your file looks like
327 // number of lines
1 2 3 // line 1
33 44 55 // line 2
... repeats until 327 lines have been printed, all with 3 elements? Note that the line breaks would be optional and could be any whitespace.
The canonical way to read a number from text in C is using scanf. scanf uses, like printf, a weird looking format string as the fist parameter. Each basic type has a letter associated with it, for integers it's d or, more intuitively, i. These letters are prefixed with a %. So to read an integer, you would write scanf("%d", &lines); if lines is an int holding the number of lines. (Do rather not use x, for readability).
The way you allocate your array is correct (provided x holds the number of lines and 10 is the known line length). One style issue is that the 10 should be #defined as a macro so that you can use e.g. malloc(LINE_LEN*sizeof(int)). That helps later when that number should ever change and you have (in a real world program) scattered references to m over several source files.
If this is just a little program and the array isnt't inordinately large and does not need to live longer than the function call (which, in the case of main(), may be long enough in any case), the easiest would be to use a variable size array in C; provided you use a modestly modern compiler:
#define LINE_LEN 10
int lineCount;
scanf("%d", &lineCount);
int m[lineCount][LINE_LEN];
// fill from file
If you compile with gcc you'll probably need to specify "-std=c99" as a command line option for that.
I'm trying to do something that should be simple. I am making an array that only has 1 element in it. Which is coordinates x y z
So I figured Id make an array with 1 row and 3 columns, 1 column for the x y and z. I don't need anymore rows because this number is going to be constantly updated and I don't need memory of the previous point, so its just going to be constantly overridden
so here is my array
int coordinates[1][3] = {1,1,1};
and this is how I am trying to see if I built it correct and that the values print out.
printf("%d %d %d\n", coordinates[1][1],coordinates[1][2],coordinates[1][3] );
printf("\n");
My thinking that it will print Row 1 column 1, Row 1 Column 2, and row 1 column 3.
What is wrong with my thinking here? I'm not getting 1 1 1 as my result. I'm getting random numbers.
I'm not too familiar with C. This seem trivial and I'm starting to spin my wheels too much on it.
EDIT: MY PROCESS OF WORKING THINGS(Also see comment)
"This was the first thing I tried. Thinking back to arrays 101 and indexing is n-1 because It seemed like I was getting elements in random memory address outside the arrays bounds. Still did not work unfortunately im starting to beat my head against a wall."
I did try
printf("%d %d %d\n", coordinates[0][0],coordinates[0][1],coordinates[0][2] );
printf("\n");
but again i got random numbers
CONCLUSION
Ok I finally figured out what I was doing wrong. You all were right. I was looking in the wrong spot of my code. Thank you for your prompt responses. What was happening was I Originally called my coordinates as a float in my code. I didnt copy and past it here so I called it an int here. SO when I was trying to printf with %d it was trying to print an int for a float causing the messed up results. I switched the %d to %f (which i was unaware how the printf worked like that i guess) and it worked!. Green horn mistake and im sorry for it! Thanks again for the help!
Remember that array index starts from 0 in C, this rule applies to multiple-dimensional arrays as well.
For an array int coordinates[1][3], its elements are coordinates[0][0], coordinates[0][1] and coordinates[0][2].
it should be indexed as cordinates[0][0], cordinates[0][1], cordinates[0][2] because array indexing usually starts at 0.
here cordinates[1][3], means row size is one but it is indexed using 0. similary columns are indexed from 0 to 3. i.e. 0 to size-1
It should be like this
printf("%d %d %d\n", coordinates[0][0],coordinates[0][1],coordinates[0][2] );
As the index starts from zero not one.
How can I run a loop in c for a very large count in c for eg. 2^1000 times?
Also, using two loops that run a and b no. of times, we get a resultant block that runs a*b no. of times. Is there any smart method for running a loop a^b times?
You could loop recursively, e.g.
void loop( unsigned a, unsigned b ) {
unsigned int i;
if ( b == 0 ) {
printf( "." );
} else {
for ( i = 0; i < a; ++i ) {
loop( a, b - 1 );
}
}
}
...will print a^b . characters.
While I cannot answer your first question, (although look into libgmp, this might help you work with large numbers), a way to perform an action a^b times woul be using recursion.
function (a,b) {
if (b == 0) return;
while (i < a) {
function(a,b-1);
}
}
This will perform the loop a times for each step until b equals 0.
Regarding your answer to one of the comments: But if I have two lines of input and 2^n lines of trash between them, how do I skip past them? Can you tell me a real life scenario where you will see 2^1000 lines of trash that you have to monitor?
For a more reasonable (smaller) number of inputs, you may be able to solve what sounds to be your real need (i.e. handle only relevant lines of input), not by iterating an index, but rather by simply checking each line for the relevant component as it is processed in a while loop...
pseudo code:
BOOL criteriaMet = FALSE;
while(1)
{
while(!criteriaMet)
{
//test next line of input
//if criteria met, set criteriaMet = TRUE;
//if criteria met, handle line of input
//if EOF or similar, break out of loops
}
//criteria met, handle it here and continue
criteriaMet = FALSE;//reset for more searching...
}
Use a b-sized array i[] where each cell hold values from 0 to a-1. For example - for 2^3 use a 3-sized array of booleans.
On each iteration. Increment i[0]. If a==i[0], set i[0] to 0 and increment i[1]. If 0==i[1], set i[1] to 0 and increment i[2], and so on until you increment a cell without reaching a. This can easily be done in a loop:
for(int j=0;j<b;++j){
++i[j];
if(i[j]<a){
break;
}
}
After a iterations, i[0] will return to zero. After a^2 iterations, i[0],i[1] will both be zero. AFter a^b iterations, all cells will be 0 and you can exit the loop. You don't need to check the array each time - the moment you reset i[b-1] you know the all the array is back to zero.
Your question doesn't make sense. Even when your loop is empty you'd be hard pressed to do more than 2^32 iterations per second. Even in this best case scenario, processing 2^64 loop iterations which you can do with a simple uint64_t variable would take 136 years. This is when the loop does absolutely nothing.
Same thing goes for skipping lines as you later explained in the comments. Skipping or counting lines in text is a matter of counting newlines. In 2006 it was estimated that the world had around 10*2^64 bytes of storage. If we assume that all the data in the world is text (it isn't) and the average line is 10 characters including newline (it probably isn't), you'd still fit the count of numbers of lines in all the data in the world in one uint64_t. This processing would of course still take at least 136 years even if the cache of your cpu was fed straight from 4 10Gbps network interfaces (since it's inconceivable that your machine could have that much disk).
In other words, whatever problem you think you're solving is not a problem of looping more than a normal uint64_t in C can handle. The n in your 2^n can't reasonably be more than 50-55 on any hardware your code can be expected to run on.
So to answer your question: if looping a uint64_t is not enough for you, your best option is to wait at least 30 years until Moore's law has caught up with your problem and solve the problem then. It will go faster than trying to start running the program now. I'm sure we'll have a uint128_t at that time.