array to pointer issue in C program - c

Here is the program which i am working on.
void primMST(int graph[N][N])
{
int parent[N] ; // Array to store constructed MST
int key[N]; // Key values used to pick minimum weight edge in cut
bool mstSet[N]; // To represent set of vertices not yet included in MST
int i, count, v;
// Initialize all keys as INFINITE
for (i = 0; i < N; i++)
key[i] = INT_MAX, mstSet[i] = false;
// Always include first 1st vertex in MST.
key[0] = 0; // Make key 0 so that this vertex is picked as first vertex
parent[0] = -1; // First node is always root of MST
// The MST will have N vertices
for (count = 0; count < N-1; count++)
{
// Pick thd minimum key vertex from the set of vertices
// not yet included in MST
int u = minKey(key, mstSet);
// Add the picked vertex to the MST Set
mstSet[u] = true;
// Update key value and parent index of the adjacent vertices of
// the picked vertex. Consider only those vertices which are not yet
// included in MST
for (v = 0; v < N; v++)
// graph[u][v] is non zero only for adjacent vertices of m
// mstSet[v] is false for vertices not yet included in MST
// Update the key only if graph[u][v] is smaller than key[v]
if (graph[u][v] && mstSet[v] == false && graph[u][v] < key[v])
parent[v] = u, key[v] = graph[u][v];
}
// print the constructed MST
printMST(parent, N, graph);
}
int main()
{
int i, j;
int** graph = (int**) malloc(sizeof(int*)*N);
for(i=0;i<N;i++)
graph[i] = (int*) malloc(sizeof(int)*N);
FILE *fp;
fp = fopen("AdjacencyMatrix_of_Graph_G_N.txt","r");
char c;
for(i=0;i<N;i++) {
for(j = 0; j < N; j++) {
fscanf(fp, "%c ", &c);
graph[i][j] = c-'0';
}
}
for(i=0;i<N;i++) {
for(j=0;j<N;j++) {
printf("%d ",graph[i][j]);
}
printf("\n");
}
primMST(graph);
fclose(fp);
return 0;
}
And i am getting the following warnings.
C:\TURBOC3\BIN\PROJECT\MST.c:125:10: warning: passing argument 1 of 'primMST' from incompatible pointer type
primMST(graph);
^
C:\TURBOC3\BIN\PROJECT\MST.c:59:6: note: expected 'int (*)[30]' but argument is of type 'int **'
void primMST(int graph[N][N])
^
Compilation results...
--------
- Errors: 0
- Warnings: 2
- Output Filename: C:\TURBOC3\BIN\PROJECT\MST.exe
- Output Size: 132.0068359375 KiB
- Compilation Time: 0.48s

as people have commented here, and int ** is not the same as int[][], and that is why the compiler complains.
also i can see that you are dynamically allocating a size of N array, this has 2 drawbacks:
1. malloc is a pretty expensive operation and calling it N times seem unnecessary.
2. the result will not be a continuous block of memory.
assuming that N is a #define, i would suggest allocating graph[N][N] on the stack in main() rather than dynamically allocating it.

Related

Function call problem in data structure learning

function call in data structure
I want to delete the i-th element in the sequence table, and delete it by calling my own defined DelList function in the main function, but after compiling, I can't print out the value of the deleted element as expected.
The code before line 48 works fine, but it seems that the DelList function cannot be called, resulting in no deleted elements being printed.
Is there a problem with calling the DelList function? Or is there a problem with the return of the DelList function?
Thank you
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
#define OK 1
#define ERROR 0
typedef int ElemType; /*Assume that the data elements in the sequence table
are integers*/
typedef struct {
ElemType elem[MAXSIZE];
int last;
}SeqList;
int DelList(SeqList *L, int i, ElemType *e)
/*The i-th data element is deleted in the sequence table L, and its value is returned with the pointer parameter e. The legal value of i is 1 ≤ i ≤ L. last +1 */
{
int k;
if ((i < 1) || (i > L->last + 1))
{
printf("Deleting the location is not legal!");
return(ERROR);
}
*e = L->elem[i - 1]; /* Store the deleted element in the variable pointed to by e*/
for (k = i; i <= L->last; k++)
L->elem[k - 1] = L->elem[k]; /*Move the following elements forward*/
L->last--;
return(OK);
}
void main()
{
SeqList *l;
int p, r;
int *q;
int i;
l = (SeqList*)malloc(sizeof(SeqList));
q = (int*)malloc(sizeof(int));
printf("Please enter the length :");
scanf("%d", &r);
l->last = r - 1;
printf("Please enter the value of each element:\n");
for (i = 0; i <= l->last; i++)
{
scanf("%d", &l->elem[i]);
}
printf("Please enter the location of the element you want to delete:\n");
scanf("%d", &p);
DelList(l, p, q);
printf("The deleted element value is:%d\n", *q);
}
Compile can pass but not the result I want
There is a small typo causing grief:
for (k = i; i <= L->last; k++) {
// ^
Here, the k index is being incremented, but not being tested against the end of the array. After writing past the end of the array, the behavior is undefined.
Change this line to:
for (k = i; k <= L->last; k++) {
// ^
Additional remarks:
I recommend using SeqList.length instead of SeqList.last. Iterating from i <= last is much less natural than i < length. One-indexing adds to the cognitive load--you can decrement user input to normalize it before sending it into your function, which can then operate on a zero-indexed array.
Consider using dynamic memory to avoid the fixed size of the array, especially if you're taking the data from I/O. At minimum, add a bounds check to avoid overflowing the buffer.
Consider using a doubly linked list if you're planning on performing frequent deletions in the middle of the list. Array deletions other than the furthest-right element are O(n), while a doubly linked list can do it in O(1). The drawback is no random access and some overhead associated with creating nodes.
Use descriptive variable names. l, p, r, q are only going to frustrate debugging efforts.
Use #include <stdbool.h> instead of #DEFINE OK 1.
Unless you're on an old compiler, variables need not be declared at the top of scopes.
No need to cast the result of malloc() (although I realize this question started out tagged C++).
Always free allocated memory. You can declare l and q on the stack and use the & reference operator to pass the address into functions.
Use int main() and return 0; from it to notify the shell that your program successfully terminated.
Here's a possible re-write that addresses some of these points:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int *data;
int length;
} SeqList;
bool list_delete(SeqList *list, int idx_to_remove, int *removed_element) {
if (idx_to_remove < 0 || idx_to_remove >= list->length) {
return false;
}
*removed_element = list->data[idx_to_remove];
list->length--;
for (int i = idx_to_remove; i < list->length; i++) {
list->data[i] = list->data[i+1];
}
return true;
}
int main() {
SeqList list;
int deleted_element;
int idx_to_delete;
printf("Please enter the length: ");
scanf("%d", &list.length);
list.data = malloc(sizeof(int) * list.length);
for (int i = 0; i < list.length; i++) {
printf("Enter the value for element %d: ", 1 + i);
scanf("%d", &list.data[i]);
}
do {
printf("Please enter the index of the element you want to delete: ");
scanf("%d", &idx_to_delete);
} while (!list_delete(&list, idx_to_delete - 1, &deleted_element));
printf("The deleted element value is: %d\n", deleted_element);
puts("The elements left in the list are:");
for (int i = 0; i < list.length; i++) {
printf("%d ", list.data[i]);
}
puts("");
free(list.data);
return 0;
}
Sample run:
Please enter the length: 4
Enter the value for element 1: 11
Enter the value for element 2: 22
Enter the value for element 3: 33
Enter the value for element 4: 44
Please enter the index of the element you want to delete: 6
Please enter the index of the element you want to delete: -1
Please enter the index of the element you want to delete: 5
Please enter the index of the element you want to delete: 4
The deleted element value is: 44
The elements left in the list are:
11 22 33

Coast length, kattis

I'm trying to solve one problem, which I found on website https://open.kattis.com/problems/coast. Tl;dr version of problem is, that for given map of landscape, I should print out length of coastline (without inner islands).
I receive 0/26 mark, but I have no idea why, I've tested, and as far as i checked, it worked. I assume it doesn't compile, but if that is the case, why is that? It compiles for me perfectly fine.
#include <stdio.h>
int edgeCount(int, int, char*);
int topToBottomCount(int, int, char*);
int leftToRightCount(int, int, char*);
int removingInsides(int, int, char*);
int main()
{
int n = 0; // number of strings
int m = 0; // strings lenghts
//printf("Enter N(number of strings) x M(strings lenght): ");
scanf("%d", &n);
scanf("%d", &m);
char coast[1024];
for(int i = 0; i < n; i++){
scanf("%s", coast+i*m); // adding strings to char coast[1024], making array of ones and zeroes // e.g we are adding 3x4 strings - 111100001111
} // it can also be looked as 1111
// 0000 - matrix
int coasts = edgeCount(n, m, coast); // 1111
coasts += topToBottomCount(n, m, coast);
coasts += leftToRightCount(n, m, coast);
coasts -= removingInsides(n, m, coast);
printf("%d - coasts\n", coasts);
return 0;
}
int edgeCount(int n, int m, char *coast){ // if 1 is placed at the edge of the "map", it is 1 coast (2 if it is at corner)
int edgeCoast = 0;
for(int i = 0; i < m; i++){ // top edges
if(coast[i] == '1')
edgeCoast++;
}
for(int i = m*n - m; i < m*n; i++){ // bottom edges (m*n - m = first char in the last string, it can be also looked as the last row in matrix)
if(coast[i] == '1')
edgeCoast++;
}
for(int i = 0; i <m*n; i+=m){ // left side edges (first column in matrix)
if(coast[i] == '1')
edgeCoast++;
}
for(int i = m-1; i < m*n; i+=m){ // right side edges (last column in matrix)
if(coast[i] == '1')
edgeCoast++;
}
return edgeCoast;
}
int topToBottomCount(int n, int m, char *coast){
int coasts = 0;
for(int i = 0; i < m*n - m; i++){ // we start from first char in "matrix", and move to the (m*n - m = 2nd last "row")
if(coast[i] ^ coast[i+m]) // we are checking if zero is placed above one or via versa
coasts++;
}
return coasts;
}
int leftToRightCount(int n, int m, char* coast){
int coasts = 0;
int p = m-1;
for(int i = 0; i < n*m; i++){ // we start from the first charr, and we are going trough whole matrix, but the last column
if(i == p){ // p = m - 1 (last char in first row)
p+=m; // p+=m (last char in next column, and so on)
continue; // we move to next iteration
}
if(i == m*n - 1) //if we are at last char in matrix, we break out from loop
break;
if(coast[i] ^ coast[i+1])
coasts++;
}
return coasts;
}
int removingInsides(int n, int m, char* coast){ // Lakes and islands in lakes are not contributing to the sea coast. we are checking if they exist.
int innerCoasts = 0;
for(int i = m + 1; i < n*m - m - 1; i ++){
if( coast[i] == '0' && coast[i] ^ coast[i-1] && coast[i] ^ coast[i+1] && coast[i] ^ coast[i-m] && coast[i] ^ coast[i+m]) // char has to be 0, and to hist left, right, above and under there has to be 1
innerCoasts++;
}
return innerCoasts * 4; // *4 because we added 4 coasts before for each island.
}
I tried compiling your code using the GCC C++ compiler (4.9.2). It compiled fine and I tested it using the sample problem in the link you provided. It spit out the right answer.
However, when I tried compiling using the GCC C compiler (also v 4.9.2), it fails with 'for' loop initial declarations are only allowed in C99 or C11 mode, which is explained by this SO question. I think your assignment was graded using a C compiler and the compilation of your program failed due to this error.

C language. How to find the maximum minimum. (2D arrays)

I have written code that allows you to enter one dimension of a NxN double array. It will then print random numbers in a 2D array and it finds the maximum and minimum number of each row. It then prints them and their coordinates (row and column).
ATTENTION!!!!
I have altered my code in such a way that it finds the minimum number of the maximum. I now don't know how to find it's coordinates
My code is as follows:
int N, i, j, min=1000, max, m , o;
time_t t;
int masyvas[100][100], minmax[100];
printf("Enter one dimension of a NxN array\n");
scanf("%d", &N);
srand((unsigned) time(&t));
for (i=0; i<N; i++)
{
for (j=0; j<N; j++)
{
masyvas[i][j] = rand() % 10;
printf("%4d", masyvas[i][j]);
}
printf("\n");
}
int k, l, idkeymax, idkeymin;
for(k=0; k<N; k++)
{
max=-1000;
for(l=0; l<N; l++)
{
if(max<masyvas[k][l])
{
max=masyvas[k][l];
}
}
minmax[k]=max;
}
for(m=0; m<N; m++)
{if(minmax[m]<min)
min=minmax[m];
}
printf("maziausias skaicius tarp didziausiu yra %d eiluteje %d stulpelyje %d\n",min);
Here's the pseudo code of what you need to do.
for row in grid {
row_max = max_in_row(row)
grid_min = min(grid_min, row_max)
}
Step one is to write a routine that finds the max and location in a list. You could do this as one big function, but it's much easier to understand and debug in pieces.
You also need the index where it was found. Since C can't return multiple values, we'll need a struct to store the number/index pair. Any time you make a struct, make routines to create and destroy it. It might seem like overkill for something as trivial as this, but it will make your code much easier to understand and debug.
typedef struct {
int num;
size_t idx;
} Int_Location_t;
static Int_Location_t* Int_Location_new() {
return calloc(1, sizeof(Int_Location_t));
}
static void Int_Location_destroy( Int_Location_t* loc ) {
free(loc);
}
Now we can make a little function that finds the max number and position in a row.
static Int_Location_t* max_in_row(int *row, size_t num_rows) {
Int_Location_t *loc = Int_Location_new();
/* Start with the first element as the max */
loc->num = row[0];
loc->idx = 0;
/* Compare starting with the second element */
for( size_t i = 1; i < num_rows; i++ ) {
if( row[i] > loc->num ) {
loc->num = row[i];
loc->idx = i;
}
}
return loc;
}
Rather than starting with some arbitrary max or min, I've used an alternative technique where I set the max to be the first element and then start checking from the second one.
Now that I have a function to find the max in a row, I can now loop over it, get the max of each row, and compare it with the minimum for the whole table.
int main() {
int grid[3][3] = {
{10, 12, 15},
{-50, -15, -10},
{1,2,3}
};
int min = INT_MAX;
size_t row = 0;
size_t col = 0;
for( size_t i = 0; i < 3; i++ ) {
Int_Location_t *max = max_in_row(grid[i], 3);
printf("max for row %zu is %d at %zu\n", i, max->num, max->idx);
if( max->num < min ) {
min = max->num;
col = max->idx;
row = i;
}
Int_Location_destroy(max);
}
printf("min for the grid is %d at row %zu, col %zu\n", min, row, col);
}
I used a different technique for initializing the minimum location, because getting the first maximum would require repeating some code in the loop. Instead I set min to the lowest possible integer, INT_MAX from limits.h which is highest possible integers. This allows the code to be used with any range of integers, there are no restrictions. This is a very common technique when working with min/max algorithms.

Graph Coloring in C: Unable to identify the logical error

I am trying to implement the graph coloring algorithm in C, this implementation is based on how we assign the colors by iterating through the adjacency matrix. I am unable to get it after assigning a color to the second vertex.
Here is the code of my program:
int n, a[10][10], i, j, k, c[10], max = 0, col, ct = 0, rt = 0, m, count = 2;
void main() {
printf("enter n\n");
scanf("%d", &n);
printf("enter the Adjacency Matrix for %d rows and %d columns\n", n, n);
for (i = 0; i < n; i++) {
c[i] = 0;
for (j = 0; j < n; j++)
scanf("%d", &a[i][j]);
}
c[0] = 1;
c[1] = 2;
for (i = 1; i < n; i++) {
for (j = 0; j < n; j++)
if (a[i][j] > 0) {
m = 0;
for (col = 0; col < n; col++) {
if (a[i][col] > 0)
rt++;
if (a[col][i] > 0)
ct++;
}
m = rt;
if (ct > rt)
m = ct;
if (m < 2) {
if (a[0][i] > 0)
c[i] = 2;
else
c[i] = 1;
} else {
c[i] = count;
if (m > max) {
max = m;
count++;
}
}
rt = 0;
ct = 0;
}
if (c[i] < 1)
if (c[i - 1] > 1)
c[i] = 1;
else
c[i] = 2;
}
printf("The proper coloring is\n");
for (i = 0; i < n; i++)
printf("c%d=%d ", i + 1, c[i]);
printf("\n");
}
Example Input:
Consider a complete graph:
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0
Expected output:
c1=1 c2=2 c3=3 c4=4
Observed output:
c1=1 c2=2 c3=3 c4=3
The error seems to be in logic, as you may have inferred by the looks of the question title. The conditional statement where you are checking if m is greater than max and then updating max and count accordingly seem to be incorrect.
I could not exactly figure out what the intended logic was, but I can tell why it is incorrect.
In your usage, you keep the maximum number of neighbors you encountered in max, and update it when you find a vertex which has more neighbors. With it, you also update count, which I think holds the color of currently highest value. Now, unless you encounter a vertex with more neighbors at each step(while traversing each row), you don't update max, and therefore you don't update count. Consequently, unless you encounter such a vertex, you keep assigning the same currently highest count to all vertices you encountered.
You should explain some more about the algorithm you implemented. However, just by looking at your code I think you should at least increment count somewhere different.
A good idea might by just keeping an array equal to the number of vertices. Then for each vertex (inside outermost loop) you can reset the array and by traversing all of the neighbors of ith vertex you can set the colors used in them, and pick the smallest unused color.
It is probably not the most efficient way to do it, but you already have an O(n3) algorithm, so I think it wouldn't hurt going this way.
Below is your code, updated to reflect the changes I mentioned.
int n,a[10][10],i,j,k,c[10],max=0,col,ct=0,rt=0,m,count=2;
int used[11]; /* indices used are from 1 to n, inclusive */
void main()
{
printf("enter n\n");
scanf("%d",&n);
printf("enter the Adjacency Matrix for %d rows and %d columns\n",n,n);
for(i=0; i < n ; i++)
{
c[i]=0;
for(j=0;j<n;j++)
scanf("%d",&a[i][j]);
}
c[0]=1;
c[1]=2;
for(i = 1 ;i < n;i++)
{
for(j = 1 ;j <= n ;j++)
used[j] = 0;
for(j = 0 ;j < i ;j++)
{
if(a[i][j] > 0)
used[c[j]] = 1;
}
for(j = 1 ;j <= n ;j++)
if(!used[j])
{
c[i] = j;
break;
}
}
printf("The proper coloring is\n");
for(i = 0;i < n ;i++)
printf("c%d=%d ",i+1,c[i]);
printf("\n");
}
What does a straightforward algorithm to colour the verices look like?
Consider all vertices in a loop and assign a colour. Vertices that have been visited already have a colour; vertices that will still be visited are still uncoloured.
Determine which colours are used by adjacent vertices that have already been coloured.
With this information, pick the lowest possible colour.
What does your algorithm look like:
Assign colour 1 to vertex 1 and colour 2 to vertex 2. (Note that vertex 2 can use the same colour as vertex 1 if the two aren't connected.)
Loop over all remaining vertices; then loop over all vertices cnnected to that.
Count the number of incoming and outgoing links to the second vertex in yet another loop. (Note that merely counting the links doesn't give you information on which colours are still available. You could have many vertices coloured with colours 3 and 4, for example, but you base your new colour on the number of links. In this example, colour 1 would be a good choice.)
Your criterion for chosing a new colour is whether the number of links is greater or equal to 2. You then assign the count, but before incrementing it. That gives you the second 3 in your example, where there should be a 4.
So you loop once too many and have a poor criterion for choosing a colour. Instead of counting the lonks, you should keep a list of used colours in adjacent nodes and base your new colour on that list.
Other stylistic issues with your code:
All your variables should be local to main; there's no reason to make them global, especially since you don't use functions.
Please be more systematic with your variable declarations. To have them all slapped together in one large definition, which even claoesces arrays and scalars, make them hard to understand.
Please use braces around all code blocks, even if they are not strictly necessary. It makes reading the code easier. Small if s without an else in the inner block such as if (ct > rt) m = ct; don't need braces, but consider using them everywhere else.

function to perform bubble sort in C providing unstable results

I am participating in Harvard's opencourse ware and attempting the homework questions. I wrote (or tried to) write a program in C to sort an array using bubble sort implementation. After I finished it, I tested it with an array of size 5, then 6 then 3 etc. All worked. then, I tried to test it with an array of size 11, and then that's when it started bugging out. The program was written to stop getting numbers for the array after it hits the array size entered by the user. But, when I tested it with array size 11 it would continuously try to get more values from the user, past the size declared. It did that to me consistently for a couple days, then the third day I tried to initialize the array size variable to 0, then all of a sudden it would continue to have the same issues with an array size of 4 or more. I un-did the initialization and it continues to do the same thing for an array size of over 4. I cant figure out why the program would work for some array sizes and not others. I used main to get the array size and values from the keyboard, then I passed it to a function I wrote called sort. Note that this is not homework or anything I need to get credit, It is solely for learning. Any comments will be very much appreciated. Thanks.
/****************************************************************************
* helpers.c
*
* Computer Science 50
* Problem Set 3
*
* Helper functions for Problem Set 3.
***************************************************************************/
#include <cs50.h>
#include <stdio.h>
#include "helpers.h"
void
sort(int values[], int n);
int main(){
printf("Please enter the size of the array \n");
int num = GetInt();
int mystack[num];
for (int z=0; z < num; z++){
mystack[z] = GetInt();
}
sort(mystack, num);
}
/*
* Sorts array of n values.
*/
void
sort(int values[], int n)
{
// this is a bubble sort implementation
bool swapped = false; // initialize variable to check if swap was made
for (int i=0; i < (n-1);){ // loops through all array values
if (values[i + 1] > values [i]){ // checks the neighbor to see if it's bigger
i++; // if bigger do nothing except to move to the next value in the array
}
else{ // if neighbor is not bigger then out of order and needs sorting
int temp = values[i]; // store current array value in temp variable for swapping purposes
values[i] = values[i+1]; //swap with neighbor
values[i+1] = temp; // swap neighbor to current array value
swapped = true; // keep track that swap was made
i++;
}
// if we are at the end of array and swap was made then go back to beginning
// and start process again.
if((i == (n-1) && (swapped == true))){
i = 0;
swapped = false;
}
// if we are at the end and swap was not made then array must be in order so print it
if((i == (n-1) && (swapped == false))){
for (int y =0; y < n; y++){
printf("%d", values[y]);
}
// exit program
break;
}
} // end for
// return;
}
You can easily use 2 nested for loops :
int i, j, temp ;
for ( i = 0 ; i < n - 1 ; i++ )
{
for ( j = 0 ; j <= n - 2 - i ; j++ )
{
if ( arr[j] > arr[j + 1] )
{
temp = arr[j] ;
arr[j] = arr[j + 1] ;
arr[j + 1] = temp ;
}
}
}
also you should now it's a c++ code not a c, because c doesn't have something like :
int mystack[num];
and you should enter a number when you're creating an array and you can't use a variable (like "int num" in your code). This is in C, but in C++ you're doing right.
The first thing to do when debugging a problem like this is ensure that the computer is seeing the data you think it should be seeing. You do that by printing out the data as it is entered. You're having trouble with the inputs; print out what the computer is seeing:
static void dump_array(FILE *fp, const char *tag, const int *array, int size)
{
fprintf(fp, "Array %s (%d items)\n", tag, size);
for (int i = 0; i < size; i++)
fprintf(fp, " %d: %d\n", i, array[i]);
}
int main(void)
{
printf("Please enter the size of the array \n");
int num = GetInt();
printf("num = %d\n", num);
int mystack[num];
for (int z = 0; z < num; z++)
{
mystack[z] = GetInt();
printf("%d: %d\n", z, mystack[z]);
}
dump_array(stdout, "Before", mystack, num);
sort(mystack, num);
dump_array(stdout, "After", mystack, num);
}
This will give you direct indications of what is being entered as it is entered, which will probably help you recognize what is going wrong. Printing out inputs is a very basic debugging technique.
Also, stylistically, having a function that should be called sort_array_and_print() suggests that you do not have the correct division of labour; the sort code should sort, and a separate function (like the dump_array() function I showed) should be used for printing an array.
As it turns out the reason why it was doing this is because when comparing an array's neighbor to itself as in:
if (values[i + 1] > values [i])
The fact that I was just checking that it is greater than, without checking if it is '=' then it was causing it to behave undesirably. So if the array is for example [1, 1, 5, 2, 6, 8] then by 1 being next to a 1, my program did not account for this behavior and acted the way it did.

Resources