Data file I am reading from:
$ cat temp.txt
0 1 2 3
4 5 6 7
8 9 10 11
C code:
#include<stdio.h>
#include<stdlib.h>
void main(){
int matsize = 12;
int numrows = 3;
int numcols = 4;
int** mat=malloc(matsize*sizeof(int*));
for(int i=0;i<numrows*numcols;++i){
mat[i]=malloc(sizeof(int));
}
FILE *file;
file=fopen("temp.txt", "r");
for(int i = 0; i < numrows; i++){
for(int j = 0; j < numcols; j++) {
if (!fscanf(file, "%d", &mat[i][j]))
break;
}
}
fclose(file);
printf("%d\n",mat[numrows-1][numcols-1]);
printf("%d\n", mat[2][3]);
printf("%d\n", mat[1][5]);
printf("%d\n", mat[0][11]);
printf("Done allocating.\n");
}
$ ./a.out
11
11
0
7
The first two outputs are both 11 as expected. For a 12 item array, I was expecting mat[1][5] and mat[0][11] to output the same thing as mat[2][3] (i.e. the 12th element, i.e. the [i+1th][j+1th] element). My understanding is that internally, the array declared here:
int** mat=malloc(matsize*sizeof(int*));
is not really a 2x3 array, rather it's just a matsize array and that accessing it via mat[i][j] just kind of divides it into [i] rows then gets the [jth] element of the ith row. Does the compiler "know" the array should be a 3x4 array because I am reading the text file in with the line if (!fscanf(file, "%d", &mat[i][j])) ? Does this scanning statement permanently change the mat object into 3 pointers of 4-length integer arrays? Or is it really just still a 12-length array, which should be accessible via dividing into two 6's, one 12, etc (if so, then why didn't the last two indexings print out the right thing)?
Follow up: If I change everything from %d/ints to %lf/doubles, I get this output with the same indexing:
11.000000
11.000000
9.000000
11.000000
Why is, for example, mat[0][11] coming out to 7 when everything is an int, but 11.000000 (as expected) when things are floats?
You should allocate a 2D array instead. It can be done as
int (*mat)[rows][cols] = malloc( sizeof(int[rows][cols]) );
However, to enable the conventient mat[i][j] syntax, you have to drop one of the dimensions in the pointer type:
int (*mat)[cols] = malloc( sizeof(int[rows][cols]) );
Not only does this get rid of the needless complexity and bugs, it also enables you to read the whole file with a single fread call, since you have a real 2D array now, instead of some fragmented pointer-to-pointer thing.
Don't forget the free(mat); at the end.
I am right know working on the cs50 programming tutorial. Here I should crack a DES-encrypted string.
First I concentrate on the creating a 64bit big array with all possible chars used in the salt.
In the next step, I throw this into two for loops to print out all possible combinations of those two for loops. And that's where I am at right now.
For debug reasons, I did just print it out with printf("%s",salt). Salt is defined as char salt[2]. But for some reason, it always prints out xx# (xx changes every time as expected, I have no idea where the # is coming from).
First I thought it might overshoot the array for some weird reason and grab the # from random memory. This is why I copied it from my online IDE into my local XCode. Still the same # symbol. And now I am confused from where the # is coming from.
Link to my code.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define _XOPEN_SOURCE // DES - implementation
#include <unistd.h>
// shorthands
#define cypher argv[1]
#define ascii_dot 46
#define ascii_slash 47
#define ascii_zero 48
#define ascii_nine 57
#define salt_size 64
#define majA 65
#define majZ 90
#define minA 97
#define minZ 122
int main(int argc, string argv[]) {
// Checking input
if (argc != 2) {
printf("<usage>\n<./crack <password_hash>");
return 1;
}
// Create a salter
// 2 * 26 for letters + 10 for numbers + dot and slash = 64 = salt_size
char salt_crystal[salt_size];
{ // Own scope to not waste space for salt_iterator
int salt_iterator = 0; // used to create salt crystals
//minuscels
for (int i = minA; i <= minZ; i++)
salt_crystal[salt_iterator++] = (char)i;
//majuscels
for (int i = majA; i <= majZ; i++)
salt_crystal[salt_iterator++] = (char)i;
//ascii_dot to 9
for (int i = ascii_dot; i <= ascii_nine; i++)
salt_crystal[salt_iterator++] = (char) i;
}
// make the salt and forward it to the next function
for (int i = 0, l = salt_size; i < l; i++) {
char salt[2];
salt[0] = salt_crystal[i];
for (int i2 = 0, l2 = salt_size; i2 < l2; i2++) {
salt[1] = salt_crystal[i2];
printf("%s ", salt); // DEBUG
}
}
}
You have not posted any code, but I'm guessing you did not null terminate the array you pass to printf()...
EDIT Good guess: You set 2 characters into char salt[2] and pass that to printf. printf prints those and continues to read characters from memory beyond the end of the salt array until it finds a '\0' byte that ends the string.
There are different ways to fix this:
you can make the array longer and set a '\0' after the characters:
char salt[3];
...
salt[2] = '\0';
printf("%s", salt);
you can use a precision value of 2 in the printf format to print at most 2 bytes from the array:
printf("%.2s", salt);
you can print individual bytes from the array:
putchar(salt[0]);
putchar(salt[1]);
As to why you consistently get an #, there is no definite answer because you are experiencing undefined behavior, so anything can happen... Note however that # has value 64 which is the value you store into local variable l. It is possible that the salt array is positioned in memory juste before the l variable. In little endian, the value 64 is stored in the first byte of l.
Also note that the name l is not recommended for a variable because it is difficult to distinguish from the number 1 in a fixed font such as this.
I've made a shuffling type program that obtains from cases[]; and arranges them in a random order.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void deal(void);
int cases[22] = {1,2,3,4,5,6,8,10,15,20,25,35,50,65,85,100,105,135,165,200,250};
int main()
{
srand(time(NULL));
int a = 0;
deal();
for(a = 0 ; a < 22 ; a++)
printf("%d \n", cases[a]);
return 0;
}
void deal(void){
int loop;
int temp;
int x;
int y;
for(loop = 0; loop < 50; loop++){
x = rand() % 22;
y = rand() % 22;
temp = cases[x];
cases[x] = cases[y];
cases[y] = temp;
}
}
However when I run the code it comes with a randomly placed 0. Where is it from and why is it there?
Example output:
6
15
0 //I don't want that
20
5
50
10
3
165
65
135
105
8
1
200
25
100
85
2
250
4
You declared int cases[22] but initialized only 21 integers into that array and therefore, the last element will be 0 when not initialized. Try to add another integer at the end of the array
It's an off by one error: Ferico Samuel's answer is correct
This is a complement:
Instead of hard coding 22 as the number of cases you should write your program like this:
// no explicit declaration of the size here. The compiler automatically
// puts the correct size depending on the number of elements that follow.
int cases[] = {1,2,3,4,5,6,8,10,15,20,25,35,50,65,85,100,105,135,165,200,250};
...
for(a = 0 ; a < sizeof(cases) / sizeof(cases[0]); a++)
...
sizeof(cases) is the size of your cases array in bytes
sizeof(cases[0]) is the size of one element of the casesarray
thus sizeof(cases) / sizeof(cases[0])is the number of elements of the array.
This way you can add more elements to the cases array without the need to change the array size elsewhere in your program.
You declare your array as:
int cases[22] = {1,2,3,4,5,6,8,10,15,20,25,35,50,65,85,100,105,135,165,200,250};
Without you know it, there is actually only 21 elements in that array. Thus, in C standard compilers, the non-initialized value would be set as zero. To correct it, add one more element to the array.
int cases[22] = {1,2,3,4,5,6,8,10,15,20,25,35,50,65,85,100,105,135,165,200,250, 500}; // add 500
And things will be okay.
Anyway, for this kind of initialization, I recommend you to put the elements in multiple lines (say, every 10 elements):
int cases[22] = {1, 2, 3, 4, 5, 6, 8, 10, 15, 20,
25, 35, 50, 65, 85, 100,105,135,165,200,
250, 500}; // add 500
And put in nice format to avoid such error.
You have the wrong number of elements in the array. C is a bit stupid, because it is designed so that a compiler can only detect if there is too many elements in an array, but never if there is too few.
To ensure the exact amount of elements, you can declare arrays like this:
#define ARRAY_ITEMS(arr) (sizeof(arr) / sizeof(*arr))
#define CASES_ITEMS 22
int cases[] = {1,2,3,4,5,6,8,10,15,20,25,35,50,65,85,100,105,135,165,200,250};
_Static_assert(ARRAY_ITEMS(cases) == CASES_ITEMS, "Wrong array size: cases");
#include<stdio.h>
int main() {
int i;
int vector[5]={6,17,28,39,410},*r; //variables declaration
r=(int*)&vector; //pointer declaration
for (i = 0; i<5;i++){ //print the array in using a loop
printf("%d ",vector[i]);
}
printf("\n\n");
for(i=0;i<5;i++){ //print the array in reverse order using a loop
vector[i] = *(r+4-i); //it should be from the last to the first but it prints it
printf("%d ",vector[i]); //differently, see below
}
return 0;}
It should be:
6 17 28 39 410
410 39 28 17 6
but it results in:
6 17 28 39 410
410 39 28 39 410
the last two should be 17 6
You are overwriting the data you're trying to read, before reading it.
Just write out the steps your code is taking manually, and you'll see it.
To do reversal in-place, you must swap values around, to avoid overwriting.
Also note that the name of an array evaluates to a pointer to the first argument, in the proper context. So this:
r=(int*)&vector;
is much better written as just:
r = vector;
You should really avoid casts, and your cast is completely unnecessary.
try this:
#include<stdio.h>
int main() {
int i;
int vector[5]={6,17,28,39,410},*r; //variables declaration
r=(int*)&vector; //pointer declaration
for (i = 0; i<5;i++){ //print the array in using a loop
printf("%d ",vector[i]);
}
printf("\n\n");
for(i=0;i<5;i++){ //print the array in reverse order using a loop
//it should be from the last to the first but it prints it
printf("%d ",*(r+4-i)); //differently, see below
}
return ( 0 );
}
In your code you are changing the first two values. So first two steps Your array
will be like this.
410 39 28 39 410
After that loop continues it will get that replaced value. You can store the replaced value in the another array.
for(i=0,j=4;i<j;i++,j--){
temp=vector[i]; // storing the value in temporary variable
vector[i] = r[j];
r[j]=temp; // assigning the value .
}
for ( i=0; i < 5 ; i ++ )
printf("%d\n",vector[i]);
so I am trying to make a matrix reader that will take a text file that contains only data for a NxN matrix such as:
10 9 8 7
6 5 4 3
2 1 0 1
Read the test file into a dynamic multidimensional array. The program will not have headers, so it will need to read the entire file in order to obtain # of rows/cols.
Once I have all the data in my array I then will be able to manipulate how I want (i.e. swapping columns/rows, reversing order, etc).
At this point I am just trying to get my program to simply output the array as it appears in the test file once the entire matrix has been read in.
Here is what I have written so far:
#include <stdio.h>
#include <stdlib.h>
int main() {
int n;
int i=0;
int j=0;
scanf("%d", &n);
int **array;
array = malloc(n * sizeof(int *));
if(array == NULL) {
printf("Out of memory\n");
exit(1);
}
for(i = 0; i < n; i++) {
array[i] = malloc(n * sizeof(int));
if(array[i] == NULL) {
printf("Out of memory\n");
exit(1);
}
}
for(i = 0; i < n; i++) {
for(j = 0; j < n; j++) {
int k;
scanf("%d", &k);
array[i][j] = k;
printf("%d ", array[i][j]);
}
}
}
And running this gives me output:
9 8 7 6 5 4 3 2 1 0 1 1 1 1 1 1 1 1 1 1 1 1... repeating 1's...
I am not sure what is wrong with my code I have been staring at it for a solid hour and have made 0 progress.
Because my output prints out about 100 different ints I feel that my problem lies in my printing loops, and I feel like it has something to do with int n, but I am not sure how to deal with this.
Any help with be greatly appreciated! Thanks.
The issue is as follows: The first number that is obtained from your file is 10 and that is being stored inside the int n close towards the beginning. That value defines the width and height of your multi-dimensional array, your matrix. You then ask for further values from that file, exactly 10 * 10 many times.
The file, however, only has 4 * 3 - 1 = 11 numbers left in it. It provides them all, right into the int k. Those values get stored inside your matrix, printed. After the 11th (or 12th if you count the first 10) the scanf starts failing. As it fails, it returns the value EOF == -1 but you do not recognize that.
Failure leaves the k as it is, although I am not sure whether it is guaranteed to remain what it previously was, since as far as I know, k could very well have another memory location allocated for itself with each cycle, since (again) as far as I know it gets cleared at the end of each loop. In your case, it does keep its value, luckily I would say, and that gets stored/printed.
In the end, you should have exactly 100 numbers printed, because of that 10 at the very beginning.
Even if you had an additional 4 at the very beginning, you'd end up with a matrix that has a wild last line with all 1s.
If you want to have a 3 by 4 matrix in your hands, consider making your file as the following example:
3 4
10 9 8 7
6 5 4 3
2 1 0 1
Then read the first value into an int n and then second one into an int m. Make first memory allocation with malloc( n * sizeof * array );, then the secondary allocations with malloc( m * sizeof ** array );.
You could also alternatively omit reading anything, deduce how many rows and columns your matrix should have by reading the amount of new-line '\n' occurrences in your file (plus one), as well as amount of numbers there are on a single line.
Edit:
Okay, let's show this you could also part: This is just an example, I'll be using a pair of scanfs for counting both the amount of lines that have at least one number inside and amount of numbers on a single line.
...
int n = 0;
int m = 0;
int discardable;
while ( scanf( "%d", &discardable ) == 1 ) {
// as long as a number has been successfully read
n++;
if ( scanf( "%*[^\n]" ) != 0 )
// discard everything until a '\n'
// and if you fail to encounter a '\n' anywhere until the file ends...
break;
}
// rewind back to the beginning of the file
rewind ( stdin );
while ( scanf( "%d", &discardable ) == 1 ) {
// as long as a number has been successfully read
m++;
if ( scanf( "%*[ \t]" ) != 0 || stdin->_ptr[0] == '\n' )
// discard every ' ' or '\t'
// if you rather get carried until the end of file, break
// else, if the upcoming character is '\n', again, break
break;
}
rewind ( stdin );
...
There you have it, n and m here should be storing the height and width of the matrix you should have, respectively.
This is just a way to do it, I can see why many could potentially just hate this, because I have made use of the FILE structure, and referred to _ptr, but whatever. I personally would prefer this any day over carrying a temporary character array and read from it.