Order pair of ints inserted by input - c

Im getting input from user and then order a order of pairs if its possible
Case 1 - 4 pairs input [1,2][2,3][3,4][4,5] This a possible input so i should order this and show 1,2,3,4,5
Case 2 -4 pairs input [1,2][2,3][3,2][4,5] this is inculent so just show a message that doesnt make sense
Im trying doing this by using a adjacency matrix but now im stuck!
I create a adjacency matrix marking user input
Case 1 Matrix would be:

Let's say you have a 2D array to collect your pairs like:
#define MAXPAIRS 20 /* if you need a constant, #define one (or more) */
#define MAXC 1024
...
char line[MAXC]; /* buffer to hold each line of input */
int pairs[MAXPAIRS][2] = {{0}}, /* 2D array to hold pairs */
npairs = 0; /* number of pairs entered */
You can read each pair into your 2D array as follows:
while (npairs < MAXPAIRS) { /* loop while array not full */
printf ("enter pair [%2d] : ", npairs); /* prompt */
if (!fgets (line, MAXC, stdin)) { /* read/validate line */
puts ("(user canceled input)");
break;
}
else if (*line == '\n') /* end input on ENTER alone */
break;
/* parse integers from line into pair */
if (sscanf (line, "%d %d", &pairs[npairs][0], &pairs[npairs][1]) != 2) {
fputs (" error: invalid integer input.\n", stderr);
continue;
}
npairs++; /* increment counter */
}
(note: if you want your prompt to ask for "pair[1]... pair[2] ..." instead of "pair[0]... pair[1]...", you can use printf ("enter pair [%2d] : ", npairs + 1); adding 1 to the npairs value.)
Which simply collects pairs from the user until the array is full, or the user signals done entering input by pressing Enter alone on the line after the last input.
With your pairs stored, you can loop over the array validating that the array is incluent, between rows (if required) and between pair values, creating your matrix as you go:
int matrix[npairs+1][npairs+1]; /* using a VLA */
for (int i = 0; i < npairs + 1; i++) { /* loop over pairs + 1 */
/* 2nd row on, check value is 1-greater than previous row */
if (i && i < npairs && pairs[i][0] - pairs[i-1][0] != 1) {
fputs (" error: not incluent - between rows.\n", stderr);
return 1;
}
/* check that pair values are adjacent, increasing */
if (i < npairs && pairs[i][1] - pairs[i][0] != 1) {
fputs (" error not incluent - between pair values.\n", stderr);
return 1;
}
for (int j = 0; j < npairs + 1; j++) /* fill row in matrix */
matrix[i][j] = i < npairs && j == i + 1 ? 1 : 0;
}
If you have made it this far, you matrix is filled and your pairs incluent and you simply need to output the matrix, e.g.
puts ("\nmatrix:"); /* output matrix */
print_matrix (npairs+1, npairs+1, matrix);
Putting it altogether along with the print_matrix() function, you would have:
#include <stdio.h>
#define MAXPAIRS 20 /* if you need a constant, #define one (or more) */
#define MAXC 1024
/* simple print matrix function */
void print_matrix (int rows, int cols, int (*arr)[cols])
{
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++)
printf (j ? " %d" : "%d", arr[i][j]);
putchar ('\n');
}
}
int main (void) {
char line[MAXC]; /* buffer to hold each line of input */
int pairs[MAXPAIRS][2] = {{0}}, /* 2D array to hold pairs */
npairs = 0; /* number of pairs entered */
while (npairs < MAXPAIRS) { /* loop while array not full */
printf ("enter pair [%2d] : ", npairs); /* prompt */
if (!fgets (line, MAXC, stdin)) { /* read/validate line */
puts ("(user canceled input)");
break;
}
else if (*line == '\n') /* end input on ENTER alone */
break;
/* parse integers from line into pair */
if (sscanf (line, "%d %d", &pairs[npairs][0], &pairs[npairs][1]) != 2) {
fputs (" error: invalid integer input.\n", stderr);
continue;
}
npairs++; /* increment counter */
}
int matrix[npairs+1][npairs+1]; /* using a VLA */
for (int i = 0; i < npairs + 1; i++) { /* loop over pairs + 1 */
/* 2nd row on, check value is 1-greater than previous row */
if (i && i < npairs && pairs[i][0] - pairs[i-1][0] != 1) {
fputs (" error: not incluent - between rows.\n", stderr);
return 1;
}
/* check that pair values are adjacent, increasing */
if (i < npairs && pairs[i][1] - pairs[i][0] != 1) {
fputs (" error not incluent - between pair values.\n", stderr);
return 1;
}
for (int j = 0; j < npairs + 1; j++) /* fill row in matrix */
matrix[i][j] = i < npairs && j == i + 1 ? 1 : 0;
}
puts ("\nmatrix:"); /* output matrix */
print_matrix (npairs+1, npairs+1, matrix);
}
(note: the use of a ternary in several places above which has the form test ? if_true : if_false (a shorthand if (test) ... else ...) It can be used virtually anywhere, function parameters, etc.., anywhere a choice is needed.)
Example Use/Output
$ ./bin/incluentpairs
enter pair [ 0] : 1 2
enter pair [ 1] : 2 3
enter pair [ 2] : 3 4
enter pair [ 3] : 4 5
enter pair [ 4] :
matrix:
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
0 0 0 0 0
Edit Per-Comment
To output the message on error you can do:
for (int i = 0; i < npairs + 1; i++) { /* loop over pairs + 1 */
/* 2nd row on, check value is 1-greater than previous row */
if (i && i < npairs && pairs[i][0] - pairs[i-1][0] != 1) {
fputs (" error: not incluent - between rows.\n", stderr);
return 1;
}
/* check that pair values are adjacent, increasing */
if (i < npairs && pairs[i][1] - pairs[i][0] != 1) {
if (i) {
char msg[64];
sprintf (msg, "contradictory %d->%d %d->%d\n",
pairs[i-1][0], pairs[i-1][1], pairs[i][0], pairs[i][1]);
fputs (msg, stderr);
}
else
fputs (" error not incluent - between pair values.\n", stderr);
return 1;
}
for (int j = 0; j < npairs + 1; j++) /* fill row in matrix */
matrix[i][j] = i < npairs && j == i + 1 ? 1 : 0;
}
Example Use/Output
$ ./bin/incluentpairs
enter pair [ 0] : 1 2
enter pair [ 1] : 2 3
enter pair [ 2] : 3 2
enter pair [ 3] : 4 5
enter pair [ 4] :
contradictory 2->3 3->2
Look things over and let me know if you have questions (just leave a comment below).

Related

How to print V in c programming in 10X10 row and column in a optimized way?

I printed V using * in specific rows and columns. I had lots of if statements. I am sharing my code below.
Is there any optimised way to print the V pattern in 10X10 row column? (without many if conditions)?
#include <stdio.h>
int main() {
int row, column;
for (row = 1; row <= 10; row++) {
for (column = 1; column <= 10; column++) {
if (row == 1 && (column == 1 || column == 10)
|| row == 3 && (column == 2 || column == 9)
|| row == 5 && (column == 3 || column == 8)
|| row == 7 && (column == 4 || column == 7)
|| row == 10 && column == 5)
printf("*");
else
printf(" ");
}
printf("\n");
}
return 0;
}
A reasonable option when you need to output arbitrary amounts of spaces is to use printf string width specifier to left-pad with spaces:
printf("%*s*", spaces, "");
The above will output the empty string, padded up to a width of the integer value spaces, and then output a *. Note that the format string %*s means that you specify both a width and then a string as extra arguments. The * in that part has nothing to do with an actual *. We add that onto the end of the format string.
So, for the V shape, each line has two * characters on it, except the last line (if the width is odd). One way to do this intuitively is to track the position of the left and the right part of the V for each line, and then do the math for determining how much padding to add.
Example:
void v(int width)
{
int l = 0, r = width;
for (; l < r; l++, r--)
{
printf("%*s*%*s\n", l, "", r-l, "*");
}
if (l == r)
printf("%*s*\n", l, "");
}
If you really want more condensed code, you can elect to roll that last line into the loop. In this case, when l == r you want to only output a single asterisk. Otherwise you want two. So you could output the string &"*"[l==r] -- that will mean that when l==r is true, you'll skip over the asterisk and it will look like an empty string (because you land on the NUL terminator).
Note this is not great style. It sacrifices readability for compactness.
void v(int width)
{
for (int l = 0, r = width; l <= r; l++, r--)
{
printf("%*s*%*s\n", l, "", r-l, &"*"[l==r]);
}
}
So, this is "efficient" in terms of compact code and not many function calls. If you instead are concerned about the format parsing of printf then you can avoid it entirely. Below, we use the same left/right bounds and just walk through each row using loops. This essentially does what our printf is doing internally, except it's more obvious what's going on:
void v(int width)
{
int l = 0, r = width-1;
for (; l <= r; l++, r--)
{
int x = 0;
for (; x < l; x++) putchar(' ');
putchar('*');
if (x < r)
{
for (x++; x < r; x++) putchar(' ');
putchar('*');
}
putchar('\n');
}
}
Now for some fun...
As an exercise, here is the printf approach but with no loops (using recursion):
void vv(int width, int row) {
if(width >= 0) {
printf("%*s*%*s\n", row, "", width, &"*"[width==0]);
vv(width-2, row+1);
}
}
void v(int width) {
vv(width, 0);
}
And here is that idea turned into an intentionally horrendous mess that looks cool. ;)
#include <stdio.h>
#define VV int
#define vV "*\0%*s%*s\n"
VV Vv( VV v ,VV
vv){if(v -->0){
printf (vV+2,
vv++ ,vV,v
,vV+ !v);
Vv(-- v,vv
);}} VV V
(VV v){
Vv(v,
1);
}
int main() {
for (int v = 1; v < 12; v++) {
printf("size %d\n", v);
V(v);
}
}
I don't think this is optimized but will be simpler and scalable with SIZE.
#include <stdio.h>
#define SIZE 10
#define MID ((SIZE-1)/2) // midst position of SIZE
#define ABS(x) ((x)<0?-(x):(x)) // absolute value of x
int main()
{
int i, j;
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
if (i % 2 == 0 && ABS(j - MID) == MID - i / 2) putchar('*');
else putchar(' ');
}
putchar('\n');
}
return 0;
}
[Explanation]
Assuming SIZE equals to 10, the value MID is calculated to be 4.
Then the v shaped asterisks will be placed symmetrically wrt the 4th column.
Let's put numbers in columns (j) and rows (i) as follows:
012345678
* * 0 ABS(0 - 4) == 4 - 0, ABS(8 - 4) == 4 - 0
1 skipped as i & 2 != 0
* * 2 ABS(1 - 4) == 4 - 1, ABS(7 - 4) == 4 - 1
3 skipped
* * 4 ABS(2 - 4) == 4 - 2, ABS(6 - 4) == 4 - 2
5 skipped
* * 6 ABS(3 - 4) == 4 - 3, ABS(5 - 4) == 4 - 3
7 skipped
* 8 ABS(4 - 4) == 4 - 4
The equations above are the conditions to put the asterisks.
For instance, in the 0th row, we want to put it on 0th column and 8th.
The condition j - 4 == +/- 4 or ABS(j - 4) == 4 will represent the conditions due to the symmetricity.
If we generarize the condition across rows, we can describe it as
i % 2 == 0 && ABS(j - MID) == MID - i / 2.
This code considers the relation between the row and the position of the *, if you are in the first row, then we want the column 0 and colum 9 to print *, then second row, we want column 1 and column 8 and so on. Thus, I used an iterator for the rows and iterator for columns to know in a concrete row which column I'm printing.
#include <stdio.h>
int main()
{
int matrix_size = 10; //Assuming is squared matrix 10x10
int counter = 0;
int i,j;
for(i=0;i<(int)(matrix_size/2);i++) {
for(j=0;j<matrix_size;j++) {
if(j==i || j==(matrix_size-1-i)) {
printf("*");
}else{
printf(" ");
}
}
printf("\n");
}
return 0;
}
EDIT: compared to tshiono solution, I write the V in just 5 rows and he prints it in 10 rows but assuming an space line between each line. Boths solutions are ok depending on what u want.
For the V shape to be symmetric, the number of rows and columns should be odd. Here is a simpler method:
#include <stdio.h>
#include <stdlib.h>
int main() {
for (int n = 11, row = 0; row < n; row++) {
for (int column = 0; column < n; column++)
putchar(" *"[2 * abs(column - n / 2) == n - 1 - row]);
printf("\n");
}
return 0;
}
Output:
* *
* *
* *
* *
* *
*
For a thicker V shape:
#include <stdio.h>
#include <stdlib.h>
int main() {
for (int n = 11, row = 0; row < n; row++) {
for (int column = 0; column < n; column++)
putchar(" *"[abs(2 * abs(column - n / 2) - (n - 1 - row)) <= 1]);
printf("\n");
}
return 0;
}
Output:
* *
** **
* *
** **
* *
** **
* *
** **
* *
***
*
Other answers take into account the specific shape of V and optimize around that.
I suggest an optimized solution for any shape.
This involves a lookup table containing all the locations of * characters composing the shape.
struct { int row,col; } shape[] = {
{1,1}, {1,10}, {3,2}, {3,9}, {5,3}, {5,8}, {7,4}, {7,7}, {10,5},
{-1,-1}
};
The last location ({-1,-1}) has the same purpose as terminating '\0' for strings.

Parsing a CSV File Problems

I tried this to parse data given in a csv file into ID, AGE, and GPA fields in a "data" file, but I don't think I'm doing this right (when I tried printing the data, its printing weird numbers). What am I doing wrong?
char data[1000];
FILE *x = fopen("database.csv","rt");
char NAME[300];
int ID[300],AGE[300],GPA[300];
int i,j;
i = 0;
while(!feof(x)) {
fgets(data,999,x);
for (j = 0; j < 300 && data[i] != ','; j++, i++) {
ID[j] = data[i];
i++;
}
for (j = 0; j < 300 && data[i] != ','; j++, i++) {
NAME[j] = data[i];
i++;
}
for (j = 0; j < 300 && ( data[i] != '\0' || data[i] != '\r' || data[i] != data[i] != '\n'); j++, i++) {
GPA[j] = data[i];
}
}
First of all: for what you're doing, you probably want to look carefully at the function strtok and the atoi macro. But given the code you posted, that's perhaps still a bit too advanced, so I'm taking a longer way here.
Supposing that the line is something like
172,924,1182
then you need to parse those numbers. The number 172 is actually represented by two or four bytes in memory, in a very different format, and the byte "0" is nothing like the number 0. What you'll read is the ASCII code, which is 48 in decimal, or 0x30 in hex.
If you take the ASCII value of a single digit and subtract 48, you will get a number, because fortunately the numbers are stored in digit order, so "0" is 48, "1" is 49 and so on.
But you still have the problem of converting the three digits 1 7 2 into 172.
So once you have 'data':
(I have added commented code to deal with a unquoted, unescaped text field inside the CSV, since in your question you mention an AGE field, but then you seem to want to use a NAME field. The case when the text field is quoted or escaped is another can of worms entirely)
size_t i = 0;
int number = 0;
int c;
int field = 0; // Fields start at 0 (ID).
// size_t x = 0;
// A for loop that never ends until we issue a "break"
for(;;) {
c = data[i++];
// What character did we just read?
if ((',' == c) || (0x0c == c) || (0x0a == c) || (0x00 == c)) {
// We have completed read of a number field. Which field was it?
switch(field) {
case 0: ID[j] = number; break;
case 1: AGE[j] = number; break;
// case 1: NAME[j][x] = 0; break; // we have already read in NAME, but we need the ASCIIZ string terminator.
case 2: GPA[j] = number; break;
}
// Are we at the end of line?
if ((0x0a == c) || (0x0c == c)) {
// Yes, break the cycle and read the next line
break;
}
// Read the next field. Reinitialize number.
field++;
number = 0;
// x = 0; // if we had another text field
continue;
}
// Each time we get a digit, the old value of number is shifted one order of magnitude, and c gets added. This is called Horner's algorithm:
// Number Read You get
// 0 "1" 0*10+1 = 1
// 1 "7" 1*10+7 = 17
// 17 "2" 17*10+2 = 172
// 172 "," Finished. Store 172 in the appropriate place.
if (c >= '0' && c <= '9') {
number = number * 10 + (c - '0');
}
/*
switch (field) {
case 1:
NAME[j][x++] = c;
break;
}
*/
}

How to identify a double \n\n with fgets/read/fread

I have a dot file, which i need to parse it into a graph structure using C.
My dot file contains 2 blocs seperated with a double \n:
the one is verticle
the other one is edges
I have tried with fgets since it reads until \n is met. It is helpfull to count the number of verticles but not whats comes after it. I don't have any idea of how i can do it
Right now I have a function like this (not complete)
int graphe_charger_dot(graphe *g, char *nom_fichier) {
FILE * f;
int n;
if ((f = fopen(nom_fichier, "r")) == 0) {
puts(nom_fichier);
puts("Erreur d'ouverture du fichier");
return -1;
}
char buffer[500];
fgets(buffer, sizeof(buffer),f);
;
if (strcmp(buffer, "graph {\n") != 0) {
puts("Erreur de compatibilité de fichier");
puts(nom_fichier);
return -1;
}
puts("Fichier ouvert et compatible");
puts("Lecture du buffer 1");
// reads the first verticles. the atoi is just here to test if i can convert an char to integer even with a non integer right after it.
fgets(buffer, sizeof(buffer),f);
n = atoi(buffer);
g->n += 1;
return 0;
}
My dot file
graph {
0;
1;
2;
3;
4;
5;
6;
7;
8;
0 -- 1;
0 -- 4;
0 -- 5;
0 -- 6;
0 -- 8;
1 -- 2;
1 -- 3;
1 -- 4;
1 -- 5;
2 -- 3;
2 -- 4;
2 -- 5;
2 -- 8;
3 -- 7;
5 -- 7;
5 -- 8;
6 -- 8;
7 -- 8;
}
and the structure of the graph
struct s_graphe {
int n; /* number of verticles */
int m; /* number of edges */
int adj[GRAPHE_ORDRE_MAX][GRAPHE_ORDRE_MAX];
/* Adjacency matrix of the graph */
};
How to identify a double \n\n ...
The prior line ended with a '\n'. With fgets(), test if buffer[0] == '\n' to see if a line begins and ends with a '\n' to detect the consecutive '\n'.
...
puts("Lecture du buffer 1");
//fgets(buffer, sizeof(buffer),f);
//n = atoi(buffer);
//g->n += 1;
while (fgets(buffer, sizeof buffer, f) && buffer[0] != '\n') {
// parse `buffer` for a vertex
}
while (fgets(buffer, sizeof buffer, f)) {
// parse `buffer` for an edge
}
My dot file contains 2 blocs separated with a double \n:
The below looks like 3 '\n' in a row. The first of the 3 ends the "8;\n" line.
7;\n
8;\n
\n
\n
0 -- 1;\n
0 -- 4;\n
In that case a little more work is needed. Perhaps
while (fgets(buffer, sizeof buffer, f) && buffer[0] != '\n') {
// parse `buffer` for a vertex
}
// Here code consumes 0 or more lines that are only `"\n"`
// Could use a counter to limit
int ch;
while ((c = fgetc(f)) == '\n');
ungetc(ch, f);
while (fgets(buffer, sizeof buffer, f)) {
// parse `buffer` for an edge
}

Reading in an array for maze file in C with an uneven size of cube and extra characters

I'm trying to figure out how to properly read in and store a maze from a .txt document in C. The max size of this maze will be 40x40 "cubes". After reading it in, I will be needing to solve it, by placing the path from the left hand corner to bottom right with a *. I'm used to using 2D Arrays, but this problem keeps tripping me up as I don't understand how to keep track of the rows and cols if they are not exactly even, or how I would even accurately print a * in the middle of each "cube" after I have solved it. I've read other examples of mazes that are composed of 1s and 0s, or all even # for the walls, which makes it easy to read in and keep track of, but not input like this. There will be other mazes on the same text file that I will need to read in after solving the first maze that will be separated by a double space. Below is an example of one of the mazes :
+---+---+---+---+---+
| | |
+---+ + + + +
| | | | | |
+ + + + +---+
| | | | |
+ + + +---+ +
| | | |
+ +---+---+ + +
| | |
+---+---+---+---+---+
Here is some of my code I am making so far to error check and read in characters. In it, I am attempting to initialize an array of 120x120, read in the current char, and convert these characters to either a -1 or 0 to correspond to a wall or empty space. :
/* Read in a grid as parameter of max 120x120 to account for '+' and'-' */
int readLine(int grid2D[120][120])
{
int row = 0;
int col = 0;
int isNewLine = TRUE;
/* Loop through while getchar does not equal EOF */
while ((c = getchar()) != EOF)
{
/* Check for foreign characters, return FALSE if found */
if ((c != '+') || (c != '-') || (c != '|') || (c != ' '))
{
/* If c = \n , avoid tripping error, and do nothing */
if(c == '\n'){}
else
errorFree = FALSE;
}
/* If character is a '+' '-' or '|', it is a wall, set to -1 to
use int's for wall tracking */
else if (row%2 == 0)
{
if(c == '|')
{
grid2D[row][col] = -1;
col++;
}
}
else if((c == '+') || (c == '-'))
{
grid2D[row][col] = -1;
col++;
}
else
{
if(c == '\n')
{
col = 0;
row++;
}
}
isNewLine = TRUE;
return isNewLine;
}
Any guidance would be greatly appreciated, I am not sure if the approach I am doing is correct. I believe I am currently error checking correctly, however I am struggling to understand how I should be keep track of the each "cube" since the chars for each "cube" are not even, they are more so dimensioned as 5x1 cubes (a +---+ for one side and a | for the other)
In response to your question and question in the comment, determining the row and column size is pretty straight forward. When you read a line of the array from the file with fgets, you can use strlen() to determine the number of characters (but note, it also contains the '\n' character - so you will need to subtract one - which you can do in combination with trimming the '\n' from the end)
Once you have read the first line and accounted for the '\n', set a variable that holds the number of characters (columns) in your array. Since you know your array is a cube, you can then compare the first-line length with the length of every other line read to validate all rows have the same number of columns.
As you are looping and handling the input of each line, you simply keep a row counter which when you are done with your read will hold the number of rows in your array.
There are two ways you can handle storage for your array. You can either declare an array large enough to hold your largest anticipated maze (while keeping it small enough to fit on the stack 256x512 is safe on both Linux and Windoze) or you can dynamically allocate storage for your columns and rows, using realloc() to allocate additional storage as required. (There you can handle maze sizes up to the memory limit of your computer - but it does add complexity)
Your "confusion" over my array needing to be, e.g. 11x21 is understandable. It all stems from the fact that characters on a terminal are roughly two-times taller than they are wide. So to print a "cube" of characters, you need roughly twice as many columns as you do rows. That isn't a problem at all. If you code your read of columns and rows properly and have variables tracking the number of columns and rows -- then the difference becomes nothing more than numbers that your code keeps track of in a couple of variables.
The following is a short example to address your stumbling blocks on the read of an unknown number or rows and columns up to a fixed maximum. (rather than dynamically allocating and reallocating -- which we can leave for later). To do so, we #define a constant for the maximum number of columns, and then knowing we need 1/2 that number of rows, #define a constant for that number of rows, e.g.
#include <stdio.h>
#include <string.h>
#define MAXC 512 /* declare consts for max NxN you can handle */
#define MAXR (MAXC + 1) / 2
Then it is a simple matter of declaring your variables to track the current row and col and the total number of rows and columns (nrow, ncol) along with declaring an array a[MAXR][MAXC] = {""}; to hold the maze. You can then either open your file if a filename is given as the 1st argument (or read from stdin by default if no argument is given). In either case, you can validate you have a stream open for reading, e.g.
size_t row = 0, col = 0, nrow = 0, ncol = 0;
char a[MAXR][MAXC+1] = {""}; /* delcare and initialize array */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
With your file stream open for reading, now it is just a matter of reading all rows of data in the file. Since you expect all lines to have an even number of characters so that your maze is actually a cube, you can save the number of characters in the first line (after trimming the '\n') and use that to compare against the number of characters in every other line to validate you have a cube. As you read lines, you also need to protect your array bounds so you don't attempt to store more lines in your array than you have rows to hold, so a simple check of row < MAXR combined with your fgets (a[row], MAXC, fp) will impose that limit, e.g.
while (row < MAXR && fgets (a[row], MAXC, fp)) {
size_t len = strlen (a[row]); /* get length of row */
if (len && a[row][len-1] == '\n') /* validate it fits in array */
a[row][--len] = 0; /* remove trailing '\n' char from end */
else if (len == MAXC) {
fprintf (stderr, "error: row exceeds %d chars.\n", MAXC);
return 1;
}
if (!row) /* if 1st row - set expected ncol for each row */
ncol = len;
if (ncol != len) { /* validate all other rows against 1st */
fprintf (stderr, "error: unequal columns (%lu) on row (%lu)\n",
len, row);
return 1;
}
/* your code goes here - example just outputs array */
for (col = 0; col < ncol; col++)
putchar (a[row][col]);
putchar ('\n');
row++; /* advance row counter when done processing row */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
nrow = row; /* save the total number of rows */
You now have all the rows and columns of stored and you have your nrow and ncol values set giving you your nrow x ncol array. The path logic I will leave to you, but I did want to provide an example of how to replace the ' ' with '*' in your path. The following does just that for every possible path character imposing the constrain that each '*' have an adjacent space (you can adjust as needed). Here we just loop 0 -> nrow-1 and nest a loop from 0 -> ncol-1 to loop over each character in the array.
The only wrinkle you have to pay attention to when checking adjacent cells in a row is that you must insure you are not on the left-edge of the maze when you check the column to the left and not on the right-edge of the maze when checking the column to the right (accessing elements beyond the bounds of your array will invoke Undefined Behavior)
You handle the edges checks as simply additions to the conditionals insider your if (...) statement, e.g.
/* you can make multiple passes over the array to determine your path.
* below is just an example of replacing the spaces in the path with
* asterisks.
*/
puts ("\nreplacing path spaces with asterisks\n");
for (row = 0; row < nrow; row++) {
for (col = 0; col < ncol; col++) {
/* if adjacents and current ' ', replace with '*' */
if (col && col < ncol - 1 && /* col > 0 && col < ncol-1 */
/* next checks adjacent and current all ' ' */
a[row][col-1] == ' ' && a[row][col] == ' ' &&
a[row][col+1] == ' ')
a[row][col] = '*'; /* if conditions met, set element '*' */
putchar (a[row][col]);
}
putchar ('\n');
}
Putting all the pieces together in a short example to read any maze up to 512 characters wide, you could do something like the following:
#include <stdio.h>
#include <string.h>
#define MAXC 512 /* declare consts for max NxN you can handle */
#define MAXR (MAXC + 1) / 2
int main (int argc, char **argv) {
size_t row = 0, col = 0, nrow = 0, ncol = 0;
char a[MAXR][MAXC+1] = {""}; /* delcare and initialize array */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (row < MAXR && fgets (a[row], MAXC, fp)) {
size_t len = strlen (a[row]); /* get length of row */
if (len && a[row][len-1] == '\n') /* validate it fits in array */
a[row][--len] = 0; /* remove trailing '\n' char from end */
else if (len == MAXC) {
fprintf (stderr, "error: row exceeds %d chars.\n", MAXC);
return 1;
}
if (!row) /* if 1st row - set expected ncol for each row */
ncol = len;
if (ncol != len) { /* validate all other rows against 1st */
fprintf (stderr, "error: unequal columns (%lu) on row (%lu)\n",
len, row);
return 1;
}
/* your code goes here - example just outputs array */
for (col = 0; col < ncol; col++)
putchar (a[row][col]);
putchar ('\n');
row++; /* advance row counter when done processing row */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
nrow = row; /* save the total number of rows */
/* you can make multiple passes over the array to determine your path.
* below is just an example of replacing the spaces in the path with
* asterisks.
*/
puts ("\nreplacing path spaces with asterisks\n");
for (row = 0; row < nrow; row++) {
for (col = 0; col < ncol; col++) {
/* if adjacents and current ' ', replace with '*' */
if (col && col < ncol - 1 && /* col > 0 && col < ncol-1 */
/* next checks adjacent and current all ' ' */
a[row][col-1] == ' ' && a[row][col] == ' ' &&
a[row][col+1] == ' ')
a[row][col] = '*'; /* if conditions met, set element '*' */
putchar (a[row][col]);
}
putchar ('\n');
}
return 0;
}
Example Use/Output
As indicated, the code simply reads and outputs the original maze and then makes a second pass over the maze outputting it with the path filled with '*'
$ ./bin/array2dread <dat/arrmaze.txt
+---+---+---+---+---+
| | |
+---+ + + + +
| | | | | |
+ + + + +---+
| | | | |
+ + + +---+ +
| | | |
+ +---+---+ + +
| | |
+---+---+---+---+---+
replacing path spaces with asterisks
+---+---+---+---+---+
| * * * | * * * * * |
+---+ * + * + * + * +
| * | * | * | * | * |
+ * + * + * + * +---+
| * | * | * | * * * |
+ * + * + * +---+ * +
| * * * | * | * * * |
+ * +---+---+ * + * +
| * * * * * * * | * |
+---+---+---+---+---+
Look things over and let me know if you have further questions.

String to space separated integer

I have a string with integers in it (in descending order) then output should be space separated integers. Integers are not negative.
INPUT: 9876543 OUTPUT: 9 8 7 6 5 4 3
INPUT: 109876543 OUTPUT: 10 9 8 7 6 5 4 3
INPUT: 400399398397 OUTPUT: 400 399 398 397
So I tried using sscanf() but was not able to get the desired result, this is the code I tried:
fgets(s1,100,stdin); // Get string
while(sscanf(data1,"%d%n",&m1,&len)==1){
b[i] = m1; // Store the integers in the array
data1 += len;
i += 1;
}
How can I achieve the desired result?
Continuing from the comments and the additional answer, to parse and separate the string into a space separated series of integers decreasing by one, there are probably a number of differing approaches you can take. The biggest design question is whether you start with the length of the input string, cut it in half and then work backwards decreasing the number of digits you check for adjacent values by one -- or whether you start at the beginning and work toward the end incrementing the number of digits being considered along the way.
Regardless of the direction you choose, the twist is handling/checking adjacent values with a different number of digits. Your second example, 109876543, hits at the heart of this twist, where you must code a way to check the 2-digit value 10 against the next single-digit value in the series 9. There is just no pretty way to do this. One reasonable way is to simply compute the smallest number that can be represented by n-digits (e.g. 10, 100, 1000, ...). Essentially 10^(n-1) (where we let int expn = n - 1;). If your first value v1 is equal to 10^(n-1), then reduce the number of characters you consider for the next smallest values. Something like the following:
while (expn--) /* loop to build 10 ^ (n-1) */
x10 *= 10; /* compute 10 ^ (n-1), 10, 100 */
if (v1 == x10) /* compare against v1 */
n--; /* reduce t2 by 1-char/digit */
The remainder of the task is just basically a brute force check with a minimum number of validations necessary to protect array bounds, while handling adding values to your integer array (or however you want to store values until you validate or invalidate the remaining characters in the string) while you work your way through the remaining characters.
Putting all the pieces together, and noting there are many, many ways to code this, this example being only one, you could do something similar to the following. Note, the code simply handles the conversion from ASCII to int in the single-digit series case by subtracting '0' from the character value, for multi-digit conversions, strtol is used with a validation check of errno. The code works from beginning to end of the string incrementing the number of digits checked until the end of the string is reached. If a solution is found, a space-separated list of integers is output, otherwise, "no solution found." is output. The code is commented to help you work though it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define MAXI 256
int main (int argc, char **argv) {
int a[MAXI] = {0}, i = 1, idx = 0, n = 1, len;
char *p = argc > 1 ? argv[1] : "9876543";
printf ("string : %s\n", p); /* original input string */
len = (int)strlen (p); /* get length */
while (i + n <= len && n < len) { /* loop until conditions met */
if (n >= MAXI) { /* protect int array bounds */
fprintf (stderr, "warning: array full, %d elements filled.\n", n);
break;
}
if (n == 1) { /* handle single digits series */
if (p[i - 1] == p[i] + 1) { /* previous equal current + 1? */
if (!idx) /* if array index == 0 */
a[idx++] = p[i - 1] - '0'; /* store first integer */
a[idx++] = p[i] - '0'; /* store current integer */
i++; /* increment string index */
}
else
n++, i = n, idx = 0; /* increment n-digits to check */
} /* set i = n, zero array index */
else { /* handle multi-digit values */
char t1[MAXI] = "", t2[MAXI] = ""; /* tmp strings for values */
int v1 = 0, v2 = 0, /* tmp for coverted values */
expn = n - 1, x10 = 1, /* 10 ^ expn for n-- test */
norig = n; /* n to restore on no match */
strncpy (t1, p + i - n, n); /* copy n-digits for 1st value */
errno = 0;
v1 = (int) strtol (t1, NULL, 10); /* convert to int/validate */
if (errno) {
fprintf (stderr, "error: failed conversion, i: %d, n: %d\n",
i, n);
return 1;
}
while (expn--) /* loop to build 10 ^ (n-1) */
x10 *= 10; /* compute 10 ^ (n-1), 10, 100 */
if (v1 == x10) /* compare against v1 */
n--; /* reduce t2 by 1-char/digit */
strncpy (t2, p + i, n); /* copy n-digits for 2nd value */
errno = 0;
v2 = (int) strtol (t2, NULL, 10); /* convert to int/validate */
if (errno) {
fprintf (stderr, "error: failed conversion, i: %d, n: %d\n",
i, n);
return 1;
}
if (v1 == v2 + 1) { /* check decreasing values */
if (!idx) /* if array index == 0 */
a[idx++] = v1; /* store first integer */
a[idx++] = v2; /* store current integer */
i += n; /* increment string index */
}
else {
n += n < norig ? 2 : 1; /* reset n if no match */
i = n; /* set string index to n */
idx = 0; /* reset array index to 0 */
}
}
}
if (idx && n < len) { /* if array has values, output */
printf ("integers :");
for (int j = 0; j < idx; j++)
printf (" %*d", n, a[j]);
putchar ('\n');
}
else
printf ("no solution found.\n");
return 0;
}
note: not all corner-cases have been evaluated and the input is presumed to contain only digits. (you are free to add the check for isdigit if you expect otherwise), further testing on your part should be done to satisfy yourself any odd-ball cases are sufficiently covered.
Example Use/Output
$ ./bin/intsepdecr
string : 9876543
integers : 9 8 7 6 5 4 3
$ ./bin/intsepdecr 109876543
string : 109876543
integers : 10 9 8 7 6 5 4 3
$ ./bin/intsepdecr 400399398397
string : 400399398397
integers : 400 399 398 397
$ ./bin/intsepdecr 400399398396
string : 400399398396
no solution found.
$ ./bin/intsepdecr 101176543
string : 101176543
no solution found.
Look things over and let me know if you have any further questions.
I can give a basic algorithm of how to go about this problem.
Convert the first x digits of the string into an integer (Initially x=1). You can even use a simple function like strtoi for this. (Let us say this number is N)
Find no of digits in N-1. Convert that many digits next into an integer.
Is the Converted value equal to N-1. If So, Continue and convert the rest of the string by repeating steps 2 & 3. (Need to Set N = N-1)
If not equal to N-1, Repeat from step 1, Only this time increment the number of digits converted.
Exit the program and declare a malformed string if you are not able to convert the entire string and x is greater than half the length of string.
Here is something i just whipped up i tested it against your cases and it works
Mind it is in c++ but it would be simple to convert to c.
string spaceNum(string in)
{
string numConvBuff;
size_t matchSize = 0;
if (in.size() == 1)
{
return to_string(in[0] - '0');
}
for (int i = 0; i < in.size() / 2; i++)
{
numConvBuff = in.substr(0, i + 1);
unsigned int numRes = stoul(numConvBuff) - 1;
string numResStr = to_string(numRes);
string n = in.substr(i + 1, numResStr.length());
if(numRes == stoul(n))
matchSize = i+1;
}
if (matchSize)
{
string out = in.substr(0, matchSize);
unsigned int numRes = stoul(out);
for (size_t i = matchSize; i < in.length();)
{
numRes--;
string numResStr = to_string(numRes);
string n = in.substr(i, numResStr.length());
out += " " + n;
i += numResStr.length();
}
return out;
}
return "";
}

Resources