How to create an adjacency matrix from an input? - c

Say I have the following raw data:
5 6
1 4 5
2 4 5
2 3 4
3 4 6
where first line represents: [number of vertices] [number of edges] and the subsequent lines represent: [index of vertex1] [index of vertex2] [weight]. I was thinking of doing %3 and dividing data into 3 strings as vertices1, vertices2 and weights, but I cant find a proper way to arrange this data into an adjacency matrix. Any suggestions?

Probbaly you need this:
#include <stdio.h>
#define MAXVERTICES 10
int main(void)
{
int matrix[MAXVERTICES][MAXVERTICES];
for (int i = 0; i < MAXVERTICES; i++)
for (int j = 0; j < MAXVERTICES; j++)
matrix[i][j] = 0;
int nbvertices, nbedges;
scanf("%d %d", &nbvertices, &nbedges);
for (int i = 0; i < nbvertices; i++)
{
int v1, v2;
int weight;
scanf("%d %d %d", &v1, &v2, &weight);
matrix[v2][v1] = matrix[v1][v2] = weight;
}
return 0;
}
It's very basic, no error checking is done and the maximum number of vertices is 10 (MAXVERTICES).

Related

Find minimum number of wires to connect the bulbs code

I have written this C code to find a minimum number of wires required to switch on all the bulbs.
The problem is that there is x number of computers, some of which are On and some are Off and the distance between these bulb from the first bulb is given. The computer can be switched ON by connecting it to its nearby ON the bulb.
So the inputs are as follows:
X = 6 (number of bulbs)
1 0 1 1 0 1(1 means the bulb is ON and 0 means the bulb is OFF)
2 4 8 36 37 40 (distance between one bulb from the first bulb)
and the output will be:
3 (Reason: 4 - 2 = 2, 37 - 36 = 1, 2 + 1 = 3)
#include <stdio.h>
int main(){
int n,pre,post,sum = 0;
scanf("%d",&n);
int arr[n],dist[n];
for(int i =0;i<n;i++){
scanf("%d ",&arr[i]);
}
for(int i =0;i<n;i++){
scanf("%d ",&dist[i]);
}
for(int i =0;i<6;i++){
if(arr[i] == 0){
pre = dist[i]-dist[i-1];
post = dist[i+1]-dist[i];
if(pre>post){
sum +=post;
}
else{
sum+=pre;
}
}
}
printf("\n %d",sum);
}
It keeps on taking the inputs. Please tell me what is the error in this code?
Thanks in advance.
Edited: I missed that scanf("%d",n) by mistake. It was there in my original code and the problem still persists.
As Sandrin mentioned, n is not defined.
Assuming your input file is:
6
1 0 1 1 0 1
2 4 8 36 37 40
You need to add code to set n:
scanf("%d ",&n);
And, you need to insert this before the definitions of your matrix
Here's the refactored code:
#include <stdio.h>
int
main(void)
{
int n, pre, post, sum = 0;
#if 1
scanf("%d ",&n);
#endif
int arr[n], dist[n];
for (int i = 0; i < n; i++)
scanf("%d ", &arr[i]);
for (int i = 0; i < n; i++)
scanf("%d ", &dist[i]);
for (int i = 0; i < 6; i++) {
if (arr[i] == 0) {
pre = dist[i] - dist[i - 1];
post = dist[i + 1] - dist[i];
if (pre > post) {
sum += post;
}
else {
sum += pre;
}
}
}
printf("\n %d", sum);
return 0;
}
Putting a side technical errors (e.g. n not initialized), the algorithms assumes that all problems can be solved by single pass. This is not true for cases like:
1 0 0 0 0 1
0 1 3 4 6 7
Where the code will choose to connect bulbs [0,1], [2,3], and [4,5], based on pre/post distances. However, bulbs 2 and 3 will remain disconnected.
A better algorithm will attempt to find, for each sequence of off bulbs, which is the most expensive connection, and avoid it.
I have come up with this solution for my code and I have tried to consider all the test cases. If you find any test case that won't run feel free to tell.
#include <stdio.h>
#include <stdlib.h>
int main(int ac, char **av){
int n,pre,post,sum = 0;
scanf("%d",&n);
int *input,*distance;
input = malloc(n * sizeof(int));
for (int i=0; i < n; i++)
{
scanf("%d", &input[i]);
}
distance = malloc(n * sizeof(int));
for (int i=0; i < n; i++)
{
scanf("%d", &distance[i]);
}
for(int i =0;i<6;i++){
if(input[i] == 0){
pre = distance[i]-distance[i-1];
if(input[i+1]==1){
post = distance[i+1]-distance[i];
input[i] =1;
if(pre>post){
sum +=post;
}
else{
sum+=pre;
}
}
else{
sum = sum+pre;
}
printf("%d.....%d....%d\n",pre,post,sum); //Debugging
}
}
printf("\n %d",sum);
free(input);
free(distance);
}

Rearranging rows in dynamically allocated 2D array in C

I'm currently working on a program in C where I input matrix dimensions and elements of a matrix, which is represented in memory as dynamic 2D array. Program later finds maximum of each row. Then it finds minimal maximum out of maximums of all rows.
For example,
if we have 3x3 matrix:
1 2 3
7 8 9
4 5 6
maximums are 3, 9, 6 and minimal maximum is 3. If minimal maximum is positive, program should proceed with rearranging order of rows so they follow ascending order of maximums, so the final output should be:
1 2 3
4 5 6
7 8 9
I made a dynamic array which contains values of maximums followed by row in which they were found, for example: 3 0 6 1 9 2. But I have no idea what should I do next. It crossed my mind if I somehow figure out a way to use this array with indices I made that I would be in problem if I have same maximum values in different rows, for example if matrix was:
1 2 3
4 5 6
7 8 9
1 1 6
my array would be 3 0 6 1 9 2 6 3. I would then need additional array for positions and it becomes like an inception. Maybe I could use some flag to see if I've already encountered the same number, but I generally, like algorithmically, don't know what to do. It crossed my mind to make an array and transfer values to it, but it would waste additional space... If I found a way to find order in which I would like to print rows, would I need an adress function different than one I already have? (which is, in double for loop, for current element - *(matrix+i * numOfCols+currentCol) ) I would appreciate if somebody told me am I thinking correctly about problem solution and give me some advice about this problem. Thanks in advance!
I don't know if I have understood it correctly, but what you want to do is to rearrange the matrix, arranging the rows by the greatest maximum to the least...
First, I don't think you need the dynamic array, because the maximums are already ordered, and their position on the array is enough to describe the row in which they are.
To order from maximum to minimum, I would make a loop which saved the position of the maximum and then, use it to store the correspondent row in the input matrix into the output matrix. Then, change the value of that maximum to 0 (if you include 0 in positives, then change to -1), and repeat the process until all rows have been passed to the output matrix. Here is a sketch of what it would look like:
for(k = 0; k < n_rows; ++k)
for(i = 0; i < n_rows; ++i)
if (max[i] > current_max)
current_max = max[i];
max_row = i;
for(c = 0; c < n_columns; ++c)
output_matrix[row][c] = inputmatrix[max_row][c];
max[max_row] = 0;
Array is not dynamic because we can not change the size of array, so in this case you can use double pointer, for example, int **matrix to store the value of 2D array.
The function for searching the max value of each row and the row index of each max value:
int * max_of_row(int n, int m, int **mat) {
// allocate for n row and the row index of max value
int *matrix = malloc (sizeof(int) * n*2);
for(int i = 0; i < 2*n; i++) {
matrix[i] = 0;
}
int k = 0;
for(int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if(matrix[k] < mat[i][j]) {
matrix[k] = mat[i][j];
}
}
matrix[k+1] = i;
k += 2;
}
return matrix;
}
The main function for test:
int main(int argc, char const *argv[])
{
// allocate for 4 rows
int **matrix = malloc (sizeof (int) * 4);
for (int i = 0; i < 4; i++) {
// allocate for 3 cols
matrix[i] = malloc(sizeof(int) * 3);
for(int j = 0; j < 3; j++){
matrix[i][j] = i+j;
}
}
int * mat = max_of_row(4, 3,matrix);
printf("matrix:\n");
for (int i = 0; i < 4; i++) {
for(int j = 0; j < 3; j++){
printf("%d ",matrix[i][j]);
}
printf("\n");
}
printf("max of row and positon\n");
for (int i = 0; i < 8; i++) {
printf("%d ", mat[i]);
}
printf("\nmax of row\n");
for (int i = 0; i < 8; i += 2) {
printf("%d ", mat[i]);
}
printf("\n");
return 0;
}
Output:
matrix:
0 1 2
1 2 3
2 3 4
3 4 5
max of row and positon
2 0 3 1 4 2 5 3
max of row
2 3 4 5

Printing a Diamond of Numbers in C

int print_pattern(){
int x;
int y;
int i;
//for loop for the bottom and the top, 0 is the top and 1 is the bottom while it stops at anything above 2.
for (i = 0; i<2;i++){
//loop to the current number
for (x=1;x<=input;x+=2){
// top or bottom, this is the top because i had made the top of the diamond the 0
// therefore this makes my diamond print the top of the function.
if ( i == 0){
//starts for the top of the diamond. and counts the spaces.
for (y=1; y<=input-x; y++){
printf(" ");
}
//starts the printing of the diamond.
for (y=1; y<2*x;y++){
printf("%d ", y);
}
}
//bottom of the diamond, which is from the 1. For this spot it take in the one from the for loop to
// this if statement.
if (i==1){
//counting spaces again
for(y = 1; y<=x; y++){
printf(" ");
}
//printing again but this is the bottom of the pyramid. #really need to comment more
for(y = 1; y<(input-x)*2;y++){
printf("%d ", y);
}
}
//next line starts when printing out the numbers in the output.
printf("\n");
}
}
}
The output is supposed to look like a diamond of the numbers ending with the odd numberat each row. but it is going +2 number past the input and then also not printing the last line. Which should have a single one.
1 1
1 2 3 1 2 3 4 5
1 2 3 4 5 1 2 3 4 5 6 7 8 9
1 2 3 1 2 3 4 5 6 7
1 1 2 3
The left is what is expected and the right is what I currently am getting when inputting 5.
Because you already increment x by 2 in the upper part, you don't need to let the print loop run to y<2*x. It should probably just run to x.
The print loop in the lower part suffers from the fact that y<(input-x)*2 should probably be y<input-x*2 (you want to print 2 less each time).
Generally I'd try to name variables in a more speaking way, like printStartPosition, maxNumToPrint, stuff like that. That makes it easier by a surprising margin to understand a program.
As an enhancement, the two code blocks depending on the i value inside the x loop are structurally very similar. One could try to exploit that and collapse both of them into a function which gets a boolean parameter like "ascending", which increments y when true and decrements it when false. Whether that improves or hinders readability would have to be seen.
Also, keep your variables local if possible.
Peter Schneider has already raised some valid points in his answer.
Think about what you have to do when you print a diamond of height 5:
print 1 centered;
print 1 2 3 centered;
print 1 2 3 4 5 centered;
print 1 2 3 centered;
print 1 centered.
Sou you could write a function that prints the numbers from 1 to n centered in a line and call it with n = 1, 3, 5, 3, 1. This can be achieved with two independent loops, one incrementing n by 2, the other decrementing it.
Another approach is to recurse: print the lines as you go deeper, incrementing n by 2 until you reach the target width, at which point you don't recurse, but return and print lines with the same parameters again as you go up. This will print each line twice except the middle one.
Here's a recursive solution:
#include <stdlib.h>
#include <stdio.h>
void print_line(int i, int n)
{
int j;
for (j = i; j < n; j++) putchar(' ');
for (j = 0; j < i; j++) printf("%d ", (j + 1) % 10);
putchar('\n');
}
void print_pattern_r(int i, int n)
{
print_line(i, n); // print top as you go deeper
if (i < n) {
print_pattern_r(i + 2, n); // go deeper
print_line(i, n); // print bottom as you return
}
}
void print_pattern(int n)
{
if (n % 2 == 0) n++; // enforce odd number
print_pattern_r(1, n); // call recursive corefunction
}
int main(int argc, char **argv)
{
int n = 0;
if (argc > 1) n = atoi(argv[1]); // read height from args, if any
if (n <= 0) n = 5; // default: 5
print_pattern(n);
return 0;
}
A JAVA STAR PATTERN PROGRAM FOR DIAMOND SHAPE converted to C Program. Code comment will explain the changes and flow.
#include <stdio.h>
#include <string.h>
void myprintf(const char* a) {
static int iCount = 0;
if (strcmp(a, "\n") == 0) {
iCount = 0; //if it is new line than reset the iCount
printf("\n"); //And print new line
} else
printf(" %d", ++iCount); //Print the value
}
void main() {
int i, j, m;
int num = 5; //Enter odd number
for (i = 1; i <= num; i += 2) { //+=2 to skip even row generation
for (j = num; j >= i; j--)
printf(" ");
for (m = 1; m <= i; m++)
myprintf(" *"); //display of star converted to number
myprintf("\n");
}
num -= 2; //Skip to generate the middle row twice
for (i = 1; i <= num; i += 2) { //+=2 to skip even row generation
printf(" ");
for (j = 1; j <= i; j++)
printf(" ");
for (m = num; m >= i; m--)
myprintf(" *"); //display of star converted to number
myprintf("\n");
}
}
Output:
1
1 2 3
1 2 3 4 5
1 2 3
1
Here's the short code for such a diamond.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int w = 9;
int l;
for(l=0; l < w; ++l)
{
printf("%*.*s\n", abs(w/2 - l)+abs((2*l+1)-(2*l+1>w)*2*w), abs((2*l+1)-(2*l+1>w)*2*w), "123456789");
}
return 0;
}

Floyd-Warshall algorithm not finding length of shortest paths correctly

This is probably a bad question to ask on SO since my rep is so low, but I have been looking through other solutions for hours, and my code seems nearly identical to the working solutions that I've come across. Please do not ignore the question based on low rep.
The output matrix, d[][] contains the (incorrect) lengths of the shortest paths between a given pair of vertices. The solution provided in the networkx library for Python has been used.
As an excerpt, the results for n=20 have been provided. I'm not printing out the paths greater than infinity (i.e. 99999), since there is overflow.
This is what the graph looks like:
My Floyd-Warshall algorithm implementation (C)
20 0 2
20 1 6
20 2 9
20 3 9
20 4 8
20 5 10
20 7 2
20 8 7
20 9 10
20 11 5
20 12 2
20 13 7
20 14 6
20 15 17
20 17 4
20 18 5
Networkx solution to Floyd-Warshall algorithm (Python)
20 0 2
20 1 5
20 2 4
20 3 4
20 4 3
20 5 7
20 7 2
20 8 2
20 9 4
20 11 4
20 12 2
20 13 6
20 14 5
20 15 4
20 17 3
20 18 4
20 20 0
Implementation:
#include <time.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#define INF 9999
#define min(a,b) (a>b)?b:a;
int n;
/*
* Method signatures
*/
void shortestPath(int matrix[][n]);
int main(){
char buf[16], c;
int i, j, weight, ret;
/* Open file handler for file containing test data */
FILE *file = fopen("eg2.txt", "r");
if(file==NULL){
puts("I/O error: cannot read input file");
fclose(file);
exit(1);
}
/* Get number of vertices in file */
fscanf(file, "%d", &n);
/* Initialise matrix of n*3 elements */
int matrix[n][n];
memset(matrix, INF, n*n*sizeof(int));
while((ret = fscanf(file, "%d %d %d", &i, &j, &weight)) != EOF) {
if(ret == 3){
matrix[i][j]=weight;
} else {
printf("ERROR: retrieved %d values (expecting 3)\n", ret);
break;
}
}
fclose(file);
/* Output matrix */
for(i=0; i<n; i++){
matrix[i][i]=0;
for(j=0; j<n; j++){
printf("%d ", matrix[i][j]);
}
printf("\n");
}
shortestPath(matrix);
}
/*
* Implementation of the Floyd-Warshall path finding algorithm
*/
void shortestPath(int matrix[][n]){
int d[n][n], k, i, j;
/* Copy values from matrix[][] to d[][] */
for(i=0; i<n; i++){
for(j=0; j<n; j++){
d[i][j] = matrix[i][j];
}
}
for(k=0; k<n; k++){
for(i=0; i<n; i++){
for(j=0; j<n; j++){
if (d[i][k] + d[k][j] < d[i][j]){
d[i][j] = d[i][k] + d[k][j];
}
}
}
}
for(i=0; i<n; i++){
for(j=0; j<n; j++){
if((d[i][j]!=0)&&(d[i][j]<INF)){
printf("%d\t%d\t%d\n", i, j, d[i][j]);
}
}
}
}
Test client (Python)
#!/usr/bin/python2.7
try:
import matplotlib.pyplot as plt
from collections import defaultdict
import networkx as nx
import numpy as np
except:
raise
nodes = defaultdict(dict)
with open('eg2.txt', 'r') as infile:
for line in infile.readlines()[1:]:
line = map(int, line.split())
src = line[0]
dst = line[1]
weight = line[2]
nodes[src][dst]=weight
G = nx.Graph()
for i in nodes:
for j in nodes[i]:
G.add_edge(i, j, weight=nodes[i][j])
rs = nx.floyd_warshall(G)
for i in rs:
for j in rs[i]:
print "%d\t%d\t%d" % (i, j, rs[i][j])
pos = nx.shell_layout(G)
nx.draw(G, pos, node_size=500, node_color='orange', edge_color='blue', width=1)
plt.axis('off')
plt.show()
Don't use dynamically sized arrays (e.g. non-constant n in the array size), they may not work the way you think. One simple way to fix your code:
#define MAXN 100
int n;
...
int matrix[MAXN][MAXN];
scanf("%d", &n);
if (n < 1 || n > MAXN) abort();
...
void shortestPath(int matrix[][MAXN]) {
Please recompile your code with all warnings enabled (e.g. gcc -W -Wall -Wextra -ansi), fix all the warnings, and indicate in the question that your code compiles without emitting any warning.
Here is a complete solution for you. I used #pts's suggestion of using a fixed array, and the suggestion from the comments of initializing the array explicitly with a pair of nested loops. I also took some liberties with the way the algorithm works - for example, with the option to have either directed or undirected graphs - and show how you can include some intermediate outputs to help in the debugging.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INF 9999
#define MIN(a,b)((a)<(b))?(a):(b)
// uncomment the next line to make processing symmetrical
// i.e. undirected edges
// #define SYM
#define NMAX 20
int n;
void shortestPath(int m[NMAX][NMAX]);
void printMatrix(int m[NMAX][NMAX]);
// implementation of floyd-warshall algorithm
// with minimal error checking
// input file = series of nodes on graph in form
// start, end, length
// algorithm attempts to find shortest path between any connected nodes
// by repeatedly looking for an intermediate node that shortens the current distance
// graphs are directional - 3 4 5 does not imply 4 3 5
// this can be changed by uncommenting the #define SYM line above
// also, hard coded to have no more than 20 nodes - defined with NMAX above
// path to input file is hard coded as "eg2.txt"
int main(void) {
int i, j, weight, ret;
// open input file:
FILE *fp = fopen("eg2.txt", "r");
if(fp == NULL) {
printf("cannot read input file\n");
exit(1);
}
// read number of nodes in the graph:
fscanf(fp, "%d", &n);
if(n > NMAX) {
printf("input too large\n");
fclose(fp);
exit(1);
}
printf("n is %d\n", n);
// generate matrix:
int matrix[NMAX][NMAX];
for(i=0; i<NMAX;i++)
for(j=0; j<NMAX; j++)
matrix[i][j] = INF;
while( (ret = fscanf(fp, "%d %d %d", &i, &j, &weight)) != EOF) {
if(ret == 3) {
matrix[i][j] = weight;
#ifdef SYM
matrix[j][i] = weight;
#endif
}
else printf("error reading input\n");
}
fclose(fp);
printMatrix(matrix);
shortestPath(matrix);
printMatrix(matrix);
}
void printMatrix(int m[NMAX][NMAX]) {
int i, j;
for(i=0; i<n; i++) {
for(j=0; j<n; j++) {
if(m[i][j]==INF) printf(" - "); else printf("%3d ", m[i][j]);
}
printf("\n");
}
}
void shortestPath(int d[NMAX][NMAX]) {
int i, j, k, temp;
// no need to make a copy of the matrix: operate on the original
for(k=0; k<n; k++) {
for(i=0; i<n-1; i++) {
for(j=0; j<n; j++) {
if(i==j) continue; // don't look for a path to yourself...
if(d[i][k] == INF || d[k][j]==INF) continue; // no path if either edge does not exist
if((temp = d[i][k] + d[k][j]) < d[i][j]) {
d[i][j] = temp;
#ifdef SYM
d[j][i] = temp;
#endif
printf("from %d to %d is shorter via %d: %d + %d is %d\n", i, j, k, d[i][k], d[k][j], temp);
}
}
}
}
for(i=0; i<n; i++) {
for(j=0; j<n; j++) {
if(d[i][j] < INF) printf("%2d %2d %3d\n", i, j, d[i][j]);
}
}
}
With the following input file:
5
1 2 3
2 4 2
1 4 8
0 3 7
3 1 2
1 4 2
1 3 1
0 1 1
I got as output:
n is 5
- 1 - 7 -
- - 3 1 2
- - - - 2
- 2 - - -
- - - - -
from 0 to 2 is shorter via 1: 1 + 3 is 4
from 0 to 3 is shorter via 1: 1 + 1 is 2
from 0 to 4 is shorter via 1: 1 + 2 is 3
from 3 to 2 is shorter via 1: 2 + 3 is 5
from 3 to 4 is shorter via 1: 2 + 2 is 4
0 1 1
0 2 4
0 3 2
0 4 3
1 2 3
1 3 1
1 4 2
2 4 2
3 1 2
3 2 5
3 4 4
- 1 4 2 3
- - 3 1 2
- - - - 2
- 2 5 - 4
- - - - -
Oddly enough, when I ran your code (as posted above) it gave me the same solution - although the output for the first part made it very clear that the memset wasn't working as you expected:
0 1 252645135 7 252645135
252645135 0 3 1 2
252645135 252645135 0 252645135 2
252645135 2 252645135 0 252645135
252645135 252645135 252645135 252645135 0
0 1 1
0 2 4
0 3 2
0 4 3
1 2 3
1 3 1
1 4 2
2 4 2
3 1 2
3 2 5
3 4 4
In fact, the number that is being written to the matrix with the memset operation is 0x0F0F0F0F, which is 252645135 in decimal. You can understand why this is so by looking at the syntax of memset:
void *memset(void *str, int c, size_t n)
Parameters
str -- This is pointer to the block of memory to fill.
c -- This is the value to be set. The value is passed as an int, but the function fills the block of memory using the unsigned char conversion of this value.
n -- This is the number of bytes to be set to the value.
and combining with the hexadecimal representation of 9999, which is
0x270F
The "unsigned char conversion" of an int is that number modulo 256, or the least significant byte. In this case, the least significant byte is 0x0F and that is the value that gets written (repeatedly) to every byte in the block - hence the value 0x0F0F0F0F (on my machine, an int is four bytes long).
Afterword
Finally - if you want to use "any size of array", you can add the following couple of functions to your program - and replace the function signatures as indicated. This is a "tricky" way to create a two D array of variable size in C - essentially, when C comes across a pointer of the type int** it will dereference twice. By making this pointer-to-a-pointer point to a block of pointers to the block of memory, you create in effect a 2D array that the compiler can understand.
int **make2D(int r, int c) {
int ii, **M;
M = malloc(r * sizeof(int*) );
M[0] = malloc( r * c * sizeof(int) );
for(ii=1; ii<r; ii++) M[ii] = M[0] + ii * c * sizeof(int);
return M;
}
void free2D(int** M) {
free(M[0]);
free(M);
}
Now you generate your matrix with
int **matrix;
matrix = make2D(n, n);
and you change the function signatures to
void shortestPath(int **m);
void printMatrix(int **m);
And call them with
shortestPath(matrix); // etc
To make everything work properly you have to make a few other adjustments in your code (example: you should not try to assign INF to all elements of a NMAX by NMAX array when you allocated less memory than that). You can try to figure this out for yourself - but just in case, here is the complete code. One other change I made - I got rid of n as a global variable and made it local to main (and passed it to the various routines that needed it). This is usually a good practice - it's all too easy to mix things up with globals, so use them only when you really have no choice.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INF 9999
#define MIN(a,b)((a)<(b))?(a):(b)
// uncomment the next line to make processing symmetrical
// i.e. undirected edges
// #define SYM
void shortestPath(int **m, int n);
void printMatrix(int **m, int n);
// create 2D matrix of arbitrary (variable) size
// using standard C:
int **make2D(int r, int c) {
int ii, **M;
M = malloc(r * sizeof(int*) );
M[0] = malloc( r * c * sizeof(int) );
for(ii=1; ii<r; ii++) M[ii] = M[0] + ii * c * sizeof(int);
return M;
}
void free2D(int** M) {
free(M[0]);
free(M);
}
// implementation of floyd-warshall algorithm
// with minimal error checking
// input file = series of nodes on graph in form
// start, end, length
// algorithm attempts to find shortest path between any connected nodes
// by repeatedly looking for an intermediate node that shortens the current distance
// graphs are directional - 3 4 5 does not imply 4 3 5
// this can be changed by uncommenting the #define SYM line above
// also, hard coded to have no more than 20 nodes - defined with NMAX above
// path to input file is hard coded as "eg2.txt"
int main(void) {
int i, j, n, weight, ret;
// open input file:
FILE *fp = fopen("eg2.txt", "r");
if(fp == NULL) {
printf("cannot read input file\n");
exit(1);
}
// read number of nodes in the graph:
fscanf(fp, "%d", &n);
printf("n is %d\n", n);
// generate matrix:
int **matrix;
// allocate memory:
matrix = make2D(n, n);
// fill all elements with INF:
for(i=0; i<n;i++)
for(j=0; j<n; j++)
matrix[i][j] = INF;
// read the input file:
while( (ret = fscanf(fp, "%d %d %d", &i, &j, &weight)) != EOF) {
if(ret == 3) {
matrix[i][j] = weight;
#ifdef SYM
// if undirected edges, put in both paths:
matrix[j][i] = weight;
#endif
}
else printf("error reading input\n");
}
fclose(fp);
printMatrix(matrix, n);
shortestPath(matrix, n);
printMatrix(matrix, n);
}
void printMatrix(int **m, int n) {
int i, j;
for(i=0; i<n; i++) {
for(j=0; j<n; j++) {
if(m[i][j]==INF) printf(" - "); else printf("%3d ", m[i][j]);
}
printf("\n");
}
}
void shortestPath(int **d, int n) {
int i, j, k, temp;
// no need to make a copy of the matrix: operate on the original
for(k=0; k<n; k++) {
for(i=0; i<n-1; i++) {
for(j=0; j<n; j++) {
if(i==j) continue; // don't look for a path to yourself...
if(d[i][k] == INF || d[k][j]==INF) continue; // no path if either edge does not exist
if((temp = d[i][k] + d[k][j]) < d[i][j]) {
d[i][j] = temp;
#ifdef SYM
d[j][i] = temp;
#endif
printf("from %d to %d is shorter via %d: %d + %d is %d\n", i, j, k, d[i][k], d[k][j], temp);
}
}
}
}
for(i=0; i<n; i++) {
for(j=0; j<n; j++) {
if(d[i][j] < INF) printf("%2d %2d %3d\n", i, j, d[i][j]);
}
}
}

Simple Input in C (Input Redirection in Shell)

I have an assignment in a beginner programming class that requires me to multiply matrices. The matrices are defined in a text file as follows:
4 5
1 5 3 2 6
3 5 4 6 3
3 5 7 5 4
4 7 8 9 7
5 3
7 1 31
0 0 5
-5 -3 2
9 41 11
0 13 31
The first number is the rows, second is the column. Then the matrix is shown, and it repeats for the second. The program must input the data into two different two dimensional arrays, multiply them, then produce a result.
I understand how to do the multiplication but I am unsure of how to get this text from a file into an array, without using file streams. We must just direct the input to the program using standard input flow.
So it should be able to run as follows on a unix platform:
./matrix < input.txt
Should I use scanf? gets? fgets? I am a fairly fluent java programmer but completely new to C. Thanks!
Since you are handling numbers only, using scanf would work fine. Just use like you are taking input from user only. The problem arises when gets and scanf are used together by inexperienced users.
int row,col,matrix[maxrow][maxcol];
scanf("%d %d",&row,&col);
for(int i = 0;i < row;i++)
{
for(int j = 0;j < col;j++)
{
scanf("%d %d",&matrix[i][j);
}
}
A simple example without check.
#include <stdio.h>
void input(int row, int col, int m[row][col]){
for(int r = 0; r < row ; ++r){
for(int c = 0; c < col ; ++c){
scanf("%d", &m[r][c]);
}
}
}
void print(int row, int col, int m[row][col]){
for(int r = 0; r < row ; ++r){
for(int c = 0; c < col ; ++c){
printf("%d ", m[r][c]);
}
printf("\n");
}
}
int main(){
int row1, col1;
scanf("%d %d", &row1, &col1);
int m1[row1][col1];
input(row1, col1, m1);
int row2, col2;
scanf("%d %d", &row2, &col2);
int m2[row2][col2];
input(row2, col2, m2);
//check print
print(row1, col1, m1);
print(row2, col2, m2);
return 0;
}

Resources