My code for dynamically allocating arrays, even though the Input methods for both arrays pattern and text are same text outputs different values, can anyone solve this issue?
#include<stdio.h>
#include<stdlib.h>
int main() {
int length=5;
int * pattern = malloc(length * sizeof(int));
int * text = malloc(length * sizeof(int));
int pattern_size=0;
int text_size=0;
printf("Enter Pattern:");
char c;
while(c != '$' && scanf("%c",&c) != '\n'){
if(pattern_size >= length)
pattern = realloc(pattern, (length += 10) * sizeof(int));
if(c!=',') pattern[pattern_size] = atoi(&c)+pattern[pattern_size]*10;
else if(c==',') {
pattern_size++;
}
}
printf("\nPlease enter the replacement text:");
// get_array(text,&text_size,length);
char d;
while(d != '$' && scanf("%c",&d) != '\n'){
if(text_size >= length)
text = realloc(text, (length += 10) * sizeof(int));
if(d!=',') text[text_size] = atoi(&d)+text[text_size]*10;
else if(d==',') {
text_size++;
}
}
for(int i=0;i<pattern_size; i++){
printf("%d ",pattern[i]);
}
printf("\n");
for(int i=0;i<text_size; i++){
printf("%d ",text[i]);
}
printf("\n");
return 0;
}
Input
Enter Pattern:1,2,3,4,5,6,7,8,9,0,$
Please enter the replacement text:1,2,3,4,5,6,7,8,9,0,$
OUTPUT
1 2 3 4 5 6 7 8 9 0
1 2 3 4 5 6 10417 8 540155953 540287027
You should ever check the return value of malloc and scanf.
Scanf does not return the element scanned. Please check man 3 scanf
On success, these functions return the number of input items
success‐ fully matched and assigned; this can be fewer than
provided for, or even zero, in the event of an early matching
failure. The value EOF is returned if the end of input is reached
before either the first successful conversion or a matching
failure occurs. EOF is also returned if a read error occurs, in
which case the error indicator for the stream (see ferror(3)) is
set, and errno is set to indicate the error.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main() {
int length = 1;
int *pattern = calloc(length, sizeof(int));
if (pattern == NULL) {
fprintf(stderr, "Unable to find free memory\n");
exit(EXIT_FAILURE);
}
int* text = calloc(length, sizeof(int));
if (text == NULL) {
fprintf(stderr, "Unable to find free memory\n");
exit(EXIT_FAILURE);
}
int pattern_size = 0;
int text_size = 0;
printf("Enter Pattern:\n");
char c = ' ';
while (c != '$') {
if (scanf("%c", &c) != 1) {
fprintf(stderr, "Error in scanf\n");
exit(EXIT_FAILURE);
}
if (isdigit(c) != 0) {
pattern[pattern_size] = c - 48;
pattern_size++;
pattern = realloc(pattern, (pattern_size + 1) * sizeof(int));
}
}
printf("\nPlease enter the replacement text:\n");
// get_array(text,&text_size,length);
char d = ' ';
while (d != '$') {
if (scanf("%c", &d) != 1) {
fprintf(stderr, "Error in scanf\n");
exit(EXIT_FAILURE);
}
if (isdigit(d) != 0) {
text[text_size] = d - 48;
text_size++;
text = realloc(text, (text_size + 1) * sizeof(int));
}
}
fprintf(stdout, "\nOUTPUT:\n");
for (int i = 0; i < pattern_size; i++)
printf("%d ", pattern[i]);
printf("\n");
for (int i = 0; i < text_size; i++)
printf("%d ", text[i]);
printf("\n");
return 0;
free(pattern);
free(text);
}
Including ctype.h you canuse the library function int isdigit(char c) that take in input a char and tells you if it is a number between 0 and 9.
Related
I want to write a program that takes numbers as inputs over multiple lines that are identified/separated by let's say ; character and print out their sum(s). Example:
1 2 3; 4 5 6; 7 8 9;(enter)
10 11 12;(enter)
exit(enter)
And I want the expected output to be exactly like:
List 1: 6 (sum of 1 2 3)
List 2: 15 (sum of 4 5 6)
List 3: 24 (sum of 7 8 9)
List 4: 33 (sum of 10 11 12)
sum of a b c, printing out this is not necessary, but their result as number is (enter), i.e. I'm pressing enter/getting to new line.
I am terminating when user types exit. But I am getting segmentation fault error in my code. Plus in this code the sum is also getting wrong values (I tried it separately).
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main() {
char *b;
int sum = 0;
int rc;
int i = 1;
while (strcasecmp(b, "exit") != 0) {
char buff[50];
rc = read(0, buff, 50);
if (rc == -1) {
perror("");
exit(0);
}
char *a = buff;
b = strtok(a, "\n");
char *c = strtok(b, ";");
while (c != NULL) {
char *d = strtok(c, " ");
while (d != NULL) {
int a = atoi(d);
sum += a;
d = strtok(NULL, " ");
printf("List %d: %d", i, sum);
i++;
}
c = strtok(NULL, ";");
}
}
}
You can use getchar and parse the integers on the go as below, without strtok.
int main() {
int sum = 0; int rc; int i = 0, j = 0;
char buff[50] = "";
while(1) {
if (i>= sizeof buff) break; //not enough memory
if (read(STDIN_FILENO, &buff[i], 1) < 1) {break;} //read error
if (strcasecmp(buff, "exit") == 0) break;
else if (buff[i] == ';'){
buff[i] = '\0';
int a = atoi(buff);
sum += a;
printf("sum = %d\n", sum);
sum = 0;
i = 0;
memset(buff, 0 , sizeof buff);
}
else if (buff[i] == ' '){
buff[i] = '\0';
int a = atoi(buff);
sum += a;
i = 0;
}
else if (buff[i] != '\n'){
i++;
}
}
}
There are multiple problems in your code:
b is an uninitialized pointer, reading and writing through it have undefined behavior, most likely the cause of the segmentation fault.
you should not use the POSIX low level functions to read input, it is non portable and the input might not be read in line chunks and will not be null terminated... Furthermore, a -1 return value is not always an error.
Use fgets() or other standard stream functions.
Here is a simple solution if you can assume that lists do not span multiple lines and are always terminated by ;:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int sumlist(int n, char *str) {
char *p, *q;
int sum = 0, term;
for (p = str;; p = q) {
p += strspn(p, " \t\n"); // skip blanks
if (*p == '\0')
break;
term = strtol(p, &q, 10);
if (q == p) {
printf("invalid input: %s\n", str);
return -1;
}
sum += term;
}
printf("List %d: %d (sum of %s)\n", n, sum, str);
return 0;
}
int main() {
char buf[200];
int n = 1;
char *p, *q;
while (fgets(buf, sizeof buf, stdin) {
for (p = str;;) {
p += strspn(p, " \t\n"); // skip initial blanks
if (*p == '\0')
break;
q = strchr(p, ';');
if (q != NULL)
*q = '\0';
if (p == q) {
p = q + 1; // skip empty lists
continue;
}
if (!strcmp(p, "exit"))
break;
sumlist(n++, p);
if (q == NULL)
break;
p = q + 1;
}
}
return 0;
}
If you cannot use fgets() or any standard stream functions, re-write your own version, reading one byte at a time from the OS handle with read() and carefully test for potential signal interrupts:
#include <errno.h>
#include <unistd.h>
char *my_gets(int hd, char *buf, size_t size) {
size_t i;
for (i = 0; i + 1 < size;) {
ssize_t n = read(hd, &buf[i], 1);
if (n != 1) {
if (n == -1 && errno == EINTR)
continue;
break;
}
if (buf[i++] == '\n')
break;
}
if (i == 0)
return NULL;
buf[i] = '\0';
return buf;
}
int main() {
char buf[200];
int n = 1;
char *p, *q;
while (my_gets(0, buf, sizeof buf) {
for (p = str;;) {
p += strspn(p, " \t\n"); // skip initial blanks
if (*p == '\0')
break;
q = strchr(p, ';');
if (q != NULL)
*q = '\0';
if (p == q) {
p = q + 1; // skip empty lists
continue;
}
if (!strcmp(p, "exit"))
break;
sumlist(n++, p);
if (q == NULL)
break;
p = q + 1;
}
}
return 0;
}
There are already working solutions here, but I'd like to suggest another one that might be helpful to understand some concepts.
Although you cannot use getc and ungetc, I would still address your problem in a way that uses the concept of a get_buf. My solution reads a character at a time and tries to turn it into a valid token that the main loop can switch on. In my opinion, that's a nice way to handle the parsing of simple 'languages' like the one you want to interpret. Also, it is pretty extensible & it's easy to add additional tokens (e.g. math operations like + - / *).
As a quick description what's happening: In get_char, a single byte is read from STDIN whenever the internal buffer is empty. If it is not, the character that's on the buffer is returned. This functionality is used by get_valid_token which returns either your delimiter ; or a (potentially multi-digit) number. Being able to 'unget' a character is required here. In main, we continuously get tokens and perform the appropriate action, nicely separating getting and interpretation of tokens. Obviously, this a quick and dirty program, but it might work for you.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUF_SIZ 2 /* get_buf never buffers more than one char by design */
static char get_buf[BUF_SIZ];
static char *get_buf_ptr = get_buf;
char get_char(int fd)
{
char c;
/* check buffer first */
if (!(get_buf == get_buf_ptr))
return *get_buf_ptr--;
/* if buffer is empty, read from STDIN */
if ((read(fd, &c, 1)) == -1) {
perror("read");
exit(1);
}
return c;
}
void unget_char(char c)
{
*(++get_buf_ptr) = c;
}
void flush(int fd)
{
char c;
do {
read(fd, &c, 1);
} while (c != '\n');
}
char is_exit()
{
if ((get_char(STDIN_FILENO)) != 'x') return 0;
if ((get_char(STDIN_FILENO)) != 'i') return 0;
if ((get_char(STDIN_FILENO)) != 't') return 0;
flush(STDIN_FILENO); /* remove already buffered input */
return 1;
}
char *get_valid_token(void)
{
char c;
char *out;
char *out_ptr;
out_ptr = out = (char *)malloc(sizeof(char)*BUFSIZ);
while (1) {
c = get_char(STDIN_FILENO);
if (c == ';') {
*out = ';';
break;
} else if (isdigit(c)) {
*out = c;
out_ptr++;
/* get the rest of the digit */
while (1) {
c = get_char(STDIN_FILENO);
if (isdigit(c)) {
*out_ptr++ = c;
} else {
unget_char(c);
break;
}
}
*out_ptr = '\0';
break;
} else if (c == 'e') {
if (is_exit())
exit(0);
}
};
return out;
}
int main(void)
{
char *t;
int sum;
sum = 0;
while ((t = get_valid_token())) {
switch (*t) {
case ';':
fprintf(stderr, "sum: %d\n", sum);
sum = 0;
break;
default:
sum += atoi(t);
break;
}
free(t);
}
return 0;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I was trying to solve CountAndSay problem at one of the online coding site but I am not able to get why my program is printing NULL. I am sure I am doing some conceptual mistake but not getting it.
Here is my code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* countAndSay(int A) {
int i,j,k,f,count;
char a;
char *c = (char*)malloc(sizeof(char)*100);
char *temp = (char*)malloc(sizeof(char)*100);
c[0] = 1;c[1] = '\0';
for(k=2; k<=A; k++)
{
for(i=0, j=0; i<strlen(c); i++)
{
a = c[i];
count = 1;
i++;
while(c[i] != '\0')
{
if(c[i]==a)
{
count++;
i++;
}
else if(c[i] != a)
{
i--;
break;
}
else
{
break;
}
}
temp[j] = count;
temp[j+1] = a;
j += 2;
}
*(temp+j) = '\0';
if(k<A)
{
for(j=0; j<strlen(temp); j++)
{
c[j] = temp[j];
}
c[j] = '\0';
}
}
return temp;
}
int main(void) {
// your code goes here
char *c = countAndSay(8);
printf("%s\n",c);
return 0;
}
The idea is not that bad, the main errors are the mix-up of numerical digits and characters as shown in the comments.
Also: if you use dynamic memory, than use dynamic memory. If you only want to use a fixed small amount you should use the stack instead, e.g.: c[100], but that came up in the comments, too. You also need only one piece of memory. Here is a working example based on your code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ALL CHECKS OMMITTED!
char *countAndSay(int A)
{
int k, count, j;
// "i" gets compared against the output of
// strlen() which is of type size_t
size_t i;
char a;
// Seed needs two bytes of memory
char *c = malloc(2);
// Another pointer, pointing to the same memory later.
// Set to NULL to avoid an extra malloc()
char *temp = NULL;
// a temporary pointer needed for realloc()-ing
char *cp;
// fill c with seed
c[0] = '1';
c[1] = '\0';
if (A == 1) {
return c;
}
// assuming 1-based input, that is: the first
// entry of the sequence is numbered 1 (one)
for (k = 2; k <= A; k++) {
// Memory needed is twice the size of
// the former entry at most.
// (Averages to Conway's constant but that
// number is not usable here, it is only a limit)
cp = realloc(temp, strlen(c) * 2 + 1);
temp = cp;
for (i = 0, j = 0; i < strlen(c); i++) {
//printf("A i = %zu, j = %zu\n",i,j);
a = c[i];
count = 1;
i++;
while (c[i] != '\0') {
if (c[i] == a) {
count++;
i++;
} else {
i--;
break;
}
}
temp[j++] = count + '0';
temp[j++] = a;
//printf("B i = %zu, j = %zu\n",i,j-1)
//printf("B i = %zu, j = %zu\n",i,j);
}
temp[j] = '\0';
if (k < A) {
// Just point "c" to the new sequence in "temp".
// Why does this work and temp doesn't overwrite c later?
// Or does it *not* always work and fails at one point?
// A mystery! Try to find it out! Some hints in the code.
c = temp;
temp = NULL;
}
// intermediate results:
//printf("%s\n\n",c);
}
return temp;
}
int main(int argc, char **argv)
{
// your code goes here
char *c = countAndSay(atoi(argv[1]));
printf("%s\n", c);
free(c);
return 0;
}
To get a way to check for sequences not in the list over at OEIS, I rummaged around in my attic and found this little "gem":
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
char *conway(char *s)
{
char *seq;
char c;
size_t len, count, i = 0;
len = strlen(s);
/*
* Worst case is twice as large as the input, e.g.:
* 1 -> 11
* 21 -> 1211
*/
seq = malloc(len * 2 + 1);
if (seq == NULL) {
return NULL;
}
while (len) {
// counter for occurrences of ...
count = 0;
// ... this character
c = s[0];
// as long as the string "s"
while (*s != '\0' && *s == c) {
// move pointer to next character
s++;
// increment counter
count++;
// decrement the length of the string
len--;
}
// to keep it simple, fail if c > 9
// but that cannot happen with a seed of 1
// which is used here.
// For other seeds it might be necessary to
// use a map with the higher digits as characters.
// If it is not possible to fit it into a
// character, the approach with a C-string is
// obviously not reasonable anymore.
if (count > 9) {
free(seq);
return NULL;
}
// append counter as a character
seq[i++] = (char) (count + '0');
// append character "c" from above
seq[i++] = c;
}
// return a proper C-string
seq[i] = '\0';
return seq;
}
int main(int argc, char **argv)
{
long i, n;
char *seq0, *seq1;
if (argc != 2) {
fprintf(stderr, "Usage: %s n>0\n", argv[0]);
exit(EXIT_FAILURE);
}
// reset errno, just in case
errno = 0;
// get amount from commandline
n = strtol(argv[1], NULL, 0);
if ((errno == ERANGE && (n == LONG_MAX || n == LONG_MIN))
|| (errno != 0 && n == 0)) {
fprintf(stderr, "strtol failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (n <= 0) {
fprintf(stderr, "Usage: %s n>0\n", argv[0]);
exit(EXIT_FAILURE);
}
// allocate space for seed value "1" plus '\0'
// If the seed is changed the limit in the conway() function
// above might need a change.
seq0 = malloc(2);
if (seq0 == NULL) {
fprintf(stderr, "malloc() failed to allocate a measly 2 bytes!?\n");
exit(EXIT_FAILURE);
}
// put the initial value into the freshly allocated memory
strcpy(seq0, "1");
// print it, nicely formatted
/*
* putc('1', stdout);
* if (n == 1) {
* putc('\n', stdout);
* free(seq0);
* exit(EXIT_SUCCESS);
* } else {
* printf(", ");
* }
*/
if (n == 1) {
puts("1");
free(seq0);
exit(EXIT_SUCCESS);
}
// adjust count
n--;
for (i = 0; i < n; i++) {
// compute conway sequence as a recursion
seq1 = conway(seq0);
if (seq1 == NULL) {
fprintf(stderr, "conway() failed, probably because malloc() failed\n");
exit(EXIT_FAILURE);
}
// make room
free(seq0);
seq0 = NULL;
// print sequence, comma separated
// printf("%s%s", seq1, (i < n - 1) ? "," : "\n");
// or print sequence and length of sequence, line separated
// printf("%zu: %s%s", strlen(seq1), seq1, (i < n-1) ? "\n\n" : "\n");
// print the endresult only
if (i == n - 1) {
printf("%s\n", seq1);
}
// reuse seq0
seq0 = seq1;
// not necessary but deemed good style by some
// although frowned upon by others
seq1 = NULL;
}
// free the last memory
free(seq0);
exit(EXIT_SUCCESS);
}
I have a program to develop but I'm having some difficulties in one part.
I have to read a number of tests (t) that will be made. After that I must read a number (n) of columns and rows to make a square matrix² (nxn). After instance of the matrix, the program must populate it from the input of the user. The user will type ., b or w. Based in this pattern I have to populate the matrix. Each line that the user will type must contain n characters (., b or w) and he will type n times. This will fill the matrix (n characters by n lines). Can you guys give me a hand?
This is the code I have:
int main(void)
{
//vars
int n = 0, t = 1, x = -1, y = -1, teste = 1;
int i,j;
//Start
scanf(" %d %*c",&t);//scans t
while (t-- > 0) {
scanf(" %d", &n);//scans n
if(n>0 && n < 100){
int table[n][n];//the matrix n x n
for (i = 0; (i < n);++i) {//iterator to lines
char l[n];
scanf ("%s", l); //scans a line
for (j = 0; j < n; ++j) {//iterator to colums
//these ifs are to identfy the input
if (l[j] == 'b'){
table[i][j]=1;
}else if(l[j] == 'w'){
table[i][j]=2;
x=j;y=i;
}else{
table[i][j]=0;
}
}
}
}
return 0;
}
I made the exactly same thing in Java and it worked. Where am I failing?
Your variable l doesn't allow enough space to store the null at the end of the string. You are therefore overflowing into some other variable, and that may be affecting all sorts of things.
You should probably read the line into a far larger string, and make sure it is the correct length. You should also error check each read operation; you should also report invalid characters in the input.
This code works for me. Note the way it echoes data so it is possible to see what's going wrong. Error reporting should really be to standard error; I've been lazy.
#include <stdio.h>
#include <string.h>
static void dump_board(FILE *fp, const char *tag, int n, int table[n][n])
{
fprintf(fp, "%s: (%d x %d)\n", tag, n, n);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (table[i][j] == 0)
putc('=', fp);
else if (table[i][j] == 1)
putc('B', fp);
else if (table[i][j] == 2)
putc('W', fp);
else
putc('?', fp);
}
putc('\n', fp);
}
}
int main(void)
{
int n = 0, t = 1, x = -1, y = -1;
if (scanf(" %d %*c", &t) != 1)
{
printf("Failed to read t\n");
return 1;
}
printf("%d data sets\n", t);
while (t-- > 0)
{
if (scanf(" %d", &n) != 1)
{
printf("Failed to read n\n");
return 1;
}
printf("Size of data set: %d x %d\n", n, n);
int c;
while ((c = getchar()) != EOF && c != '\n')
;
if (n > 0 && n < 100)
{
int table[n][n];
for (int i = 0; i < n; i++)
{
char line[4096];
if (fgets(line, sizeof(line), stdin) == 0)
break;
int len = strlen(line);
if (line[len-1] != '\n')
{
printf("Format error: line too long (%d bytes)\n", len);
return 1;
}
line[--len] = '\0';
if (len != n)
{
printf("Format error: line <<%s>> is not length %d\n", line, n);
return 1;
}
for (int j = 0; j < n; ++j)
{
if (line[j] == 'b')
table[i][j] = 1;
else if (line[j] == 'w')
{
table[i][j] = 2;
x = j;
y = i;
}
else if (line[j] == '.')
table[i][j] = 0;
else
{
printf("Format error: invalid character %c\n", line[j]);
return 1;
}
}
}
dump_board(stdout, "Input", n, table);
printf("Last white piece at (%d,%d)\n", x, y);
}
}
return 0;
}
Input
2x
4
b..w
.bw.
.b.b
w.w.
8
b.w.b.w.
.w.b.w.b
bbwwbbww
b......w
ww....bb
bwb..wbw
bbbbwwww
........
Output
2 data sets
Size of data set: 4 x 4
Input: (4 x 4)
B==W
=BW=
=B=B
W=W=
Last white piece at (2,3)
Size of data set: 8 x 8
Input: (8 x 8)
B=W=B=W=
=W=B=W=B
BBWWBBWW
B======W
WW====BB
BWB==WBW
BBBBWWWW
========
Last white piece at (7,6)
I have a problem with an "add calculator".
Valgrind reports no memory errors, no errors from compiler but the program doesn't show any output despite the printf - "Base is ".
All pointers, and variables are (n my opinion) correctly initialized.
getnum function gets a number, returns a pointer to char - char *,
add function processes two numbers as strings, returns result which is a pointer to char (char *) as well.
I don't know whether the problem is memory allocation or procedures connected to processing arrays...
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define MAX(A,B) ((A)>(B) ? (A) : (B))
char *getnum(FILE *infile, int base)
{
int len = 10;
int c;
int pos = 0;
char *num = NULL;
char *tmpnum = NULL;
num = malloc(sizeof(char)*len);
while (((c = fgetc(infile)) != EOF) && (isalnum(c))) {
if (isdigit(c)) {
/* irrelevant*/
}
else if (isalpha(c)) {
fprintf(stderr, "Wrong base, expected 16\n");
free(num);
return NULL;
}
if (pos >= len) {
/*realloc*/
}
}
return num;
}
int main(int argc, char **argv)
{
FILE *infile = NULL;
char *number1 = NULL;
char *number2 = NULL;
char *result = NULL;
int base, i, j = 0, length, count = 0;
infile = fopen(argv[1], "r");
base = atoi(argv[2]);
while (!feof(infile)) {
number1 = getnum(infile, base);
number2 = getnum(infile, base);
break;
}
printf("Base is %d\n", base);
result = add(number1, number2, base);
length = strlen(result);
for (i = 0; i <= length - 1; i++) {
if (result[i] == '0') {
count++;
}
}
for (j = i; j == (length - 1); j++) {
printf("Result is: %s\n", &result[j]);
break;
}
free(result);
result = NULL;
fclose(infile);
return 0;
}
Trying to work it out for the past 4 hours and can't find a mistake.
Thanks in advance!
There is one severe typo near the end of main().
for (j = i; j == (length - 1); j++) {
/* ^^ SHOULD BE <= */
printf("Result is: %s\n", &result[j]);
break;
}
Looking at this code:
for (i = 0; i <= length - 1; i++) {
if (result[i] == '0') {
count++;
}
}
if (count == length) {
printf("Result is 0\n");
free(result);
result = NULL; /* arguable */
fclose(infile);
return 0;
}
for (i = 0; i <= length - 1; i++) {
if (result[i] != '0') {
break;
}
}
for (j = i; j == (length - 1); j++) {
printf("Result is: %s\n", &result[j]);
break;
}
Instead of counting the total number of zeroes in the output number, and then counting the number of leading zeroes again, why not combine the two?
What is the last loop about? It's not even really a loop - it will execute once if i is length - 1, or not at all if not (presumably you're hitting the latter case in your test input).
e.g.
for (count = 0; count < length; count++) {
if (result[count] != '0')
break;
}
if (count == length) {
printf("Result is 0\n");
free(result);
result = NULL; /* arguable */
fclose(infile);
return 0;
}
printf("Result is: %s\n", &result[count]);
I would like to ask for help with allocation .... I got this homework to school...I have to write program which will load one G matrix and second G matrix and will search second G matrix for number of presences of the first G matrix....But, when I try to run my program I got Segmentation fault message... Thanks in advance.
Example how the program is supposed to work....
...
Enter number of lines of wanted g matrix:
3
Enter the wanted g matrix:
121212
212121
121212
G matrix to be searched:
12121212121212
21212121212121
12121212123212
21212121212121
12121212121212
G matrix found 8 times.
...
this is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * get_line(void) // get line
{
char * string;
if((string = (char *)malloc(100 * sizeof(char))) == NULL)
{
printf("Nedostatek pameti.\n"); // not enough memory
exit(1);
}
int i = 0;
while((string[i] = fgetc(stdin)) != '\n')
{
i++;
if((i % 100) == 0)
{
if((string = (char *)realloc(string, 100 * ( i - 1 ) * sizeof(char))) == NULL)
{
printf("Nedostatek pameti.\n"); // not enough memory
exit(1);
}
}
}
return ( string );
}
char ** get_wanted_g_matrix(int pocetradek /*number of lines*/) // get wanted g matrix
{
char ** string;
printf("Zadejte hledanou matici:\n");
int i = 0;
if(( * string = (char ** )malloc(100 * sizeof(char *))) == NULL)
{
printf("Nedostatek pameti.\n"); // not enough memory
exit(1);
}
while(i <= (pocetradek - 1))
{
string[i] = get_line();
if((i > 1) && (*string[i-1] != strlen(*string[i])))
{
printf("Nespravny vstup.\n"); // not enough memory
exit(1);
}
printf("%s", string[i]);
i++;
if((i % 100) == 0)
{
if((* string = (char **)realloc(* string, 100 * ( i - 1 ) * sizeof(char *))) == NULL)
{
printf("Nedostatek pameti.\n"); // not enough memory
exit(1);
}
}
}
return (string);
}
int get_number_of_lines(void) // get number of lines
{
int number_of_lines;
printf("Zadejte pocet radek hledane matice:\n"); // enter the number of lines of wanted g matrix
if(scanf("%d", &number_of_lines) != 1)
{
printf("Nespravny vstup.\n"); // Error
exit(1);
}
return ( number_of_lines );
}
char ** get_searched_g_matrix(void) // get wanted g matrix
{
char ** string;
printf("Matice, ktera bude prohledana:\n"); // G matrix to be searched
int i = 0;
if(( * string = (char ** )malloc(100 * sizeof(char *))) == NULL)
{
printf("Nedostatek pameti.\n"); // not enough memory
exit(1);
}
while(!feof(stdin))
{
string[i] = get_line();
if((i > 1) && (*string[i-1] != strlen(*string[i])))
{
printf("Nespravny vstup.\n"); // error
exit(1);
}
printf("%s", string[i]);
i++;
if((i % 100) == 0)
{
if((* string = (char **)realloc(* string, 100 * ( i - 1 ) * sizeof(char *))) == NULL)
{
printf("Nedostatek pameti.\n"); // not enough memory
exit(1);
}
}
}
if(feof(stdin))
{
return string;
}
}
int search( char ** string1, char ** string2 ) // search
{
int string1width = strlen(*string1[0]);
int string2width = strlen(*string2[0]);
int string2height = strlen(**string2);
int number_of_lines = get_number_of_lines();
unsigned int g = 0, h = 0, i2, j2, l = 0, i = 0, j;
while( i <= (string2height - 2) )
{
j = 0;
while( j <= string2width - 2 )
{
g = 0; h = 0;
if(string2[i][j] == string1[g][h])
{
i2 = i;
while((g <= number_of_lines - 1) && (i2 <= string2height - 2))
{
j2 = j; h = 1;
while(((string2[i2][j2] == string1[g][h]) && (j2 <= string2height - 2)) && (h <= string1width - 2))
{
j2++;
h++;
}
if(h != string1width - 1)
{
break;
}
if(g == number_of_lines - 1)
{
l++;
break;
}
i2++;
g++;
}
}
j++;
}
i++;
}
return ( l );
}
int main(void)
{
char ** string1;
char ** string2;
int number_of_lines = get_number_of_lines();
string1 = get_wanted_g_matrix(number_of_lines);
string2 = get_searched_g_matrix();
if(feof(stdin))
{
printf("Matice nalezena %d krat.\n", search( ** string1, **string2 )); // G matrix found %d times.
}
return 0;
}
In this code:
char ** get_wanted_g_matrix(int pocetradek /*number of lines*/) // get wanted g matrix
{
char ** string;
printf("Zadejte hledanou matici:\n");
int i = 0;
if(( * string = (char ** )malloc(100 * sizeof(char *))) == NULL)
You dereference string, but it is uninitialized, so you're writing to a random location in memory. Change that * string to just string. The same applies here:
if((* string = (char **)realloc(* string, 100 * ( i - 1 ) * sizeof(char *))) == NULL)
..and to the corresponding lines in get_searched_g_matrix() as well.
In this line:
if((i > 1) && (*string[i-1] != strlen(*string[i])))
You're passing a char to strlen(), when you should be passing a char *. I suspect you mean just strlen(string[i]), but that line seems somewhat nonsensical. The same problem is in get_searched_g_matrix() as well, as well as the first three calls to strlen() in search().
Your get_searched_g_matrix() can fall off the end without returning a value - you need to consider what to return if feof(stdin) is not true.
In main(), your call to search() passes char values, but the function expects char **. You probably mean:
printf("Matice nalezena %d krat.\n", search( string1, string2 ));
(The above won't be sufficient to fix your code - you also appear to have some logic problems. But it's a necessary start.)
In future, you should compile your code with a higher level of warnings enabled, then fix the problems that the compiler identifies (if you're using gcc, compile with -Wall).
Just some comments and style hints:
I'd say it's quite large for what it should do (and hard to follow), try simplifying it a bit.
1) Save vertical space, most people nowadays have wide screens, and it's quite annoing when you can't see the corresponding closing bracket.
1.1) It's very good that you check for error conditions, but try using something like
void err(const char* msg){
printf("\n\nFATAL ERROR: %s\n", msg);
exit(1);
};
so that you can do
if (!(x = malloc(sz)))
err("Not enough memory!");
1.2) While it's considered safer to use brackets for a signle statement in if, I'd suggest avoiding them when possible, or at least use fewer newlines. Brackets are for compiler, people preffer tabs.
2) There are several while statements in your search function that should be written as fors.
3) Why would you need two distinct functions to read the matrices? One would be enough.
4) As #caf pointed out, you have also errors in input functions. Test each function before going further. It takes years of experience before you can write the whole program at once.