Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 months ago.
Improve this question
I have to copy the resulting strings from the streaming input to the strings of my two-dimensional array. Is it possible to do this at all and what is wrong in my code?
The task is to getchar() strings and put them in two-dimensional array
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *arr = NULL;
char string[50];
char sym;
int counter = 0;
int counter_str = 0;
int i = 0;
while((sym = getchar()) != EOF)
{
if((sym != ' ') && (sym != ('\t') && (sym != '\n'))){
string[counter] = sym;
counter += 1;
}
if(sym == '\n'){
string[counter] = sym;
counter += 1;
counter_str += 1;
string[counter] = '\0';
arr = (char*) realloc(arr, counter_str * sizeof(char));
arr[counter_str - 1] = malloc(1 + strlen(string));
strcpy(arr[counter_str - 1], string);
counter = 0;
}
}
}
char *arr is a pointer to a char and not the 2d array you had in mind.
getchar() returns an int and EOF is usually defined as -1. It is implementation defined if char is signed or unsigned.
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR_LEN 50
int main() {
char **arr = NULL;
char string[STR_LEN];
int counter = 0;
int counter_str = 0;
for(; counter + 1 < STR_LEN;) {
int sym = getchar();
if(sym == EOF)
break;
if(sym != ' ' && sym != '\t')
string[counter++] = sym;
if(sym == '\n') {
string[counter] = '\0';
char **tmp = realloc(arr, (counter_str + 1) * sizeof(*arr));
if(!tmp) {
printf("realloc failed\n");
return 1;
}
arr = tmp;
arr[counter_str] = strdup(string);
if(!arr[counter_str]) {
printf("strdup failed\n");
return 1;
}
counter = 0;
counter_str++;
}
}
for(int i = 0; i < counter_str; i++) {
printf("%s", arr[i]);
free(arr[i]);
}
free(arr);
}
and example run:
hello world
again
helloworld
again
Unless you are super concerned about fitting as many non-space and non-tab characters it might be clearer to just read then strip the string:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR_LEN 50
void strip(char *s, const char *accept) {
for(;;) {
s = strpbrk(s, accept);
if(!s)
break;
*s = s[1];
}
}
int main(void) {
char **arr = NULL;
for(size_t i = 0;; i++) {
char **tmp = realloc(arr, (i + 1) * sizeof(*arr));
if(!tmp) {
printf("realloc failed\n");
return 1;
}
arr = tmp;
arr[i] = malloc(STR_LEN);
if(!arr[i]) {
printf("malloc failed\n");
return 1;
}
if(!fgets(arr[i], STR_LEN, stdin)) {
free(arr[i]);
arr[i] = NULL;
break;
}
strip(arr[i], " \t");
}
for(size_t i = 0; arr[i]; i++) {
printf("%s", arr[i]);
free(arr[i]);
}
free(arr);
}
Especially if you can bound the number of strings (N):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 3
#define STR_LEN 50
void strip(char *s, const char *accept) {
for(;;) {
s = strpbrk(s, accept);
if(!s)
break;
*s = s[1];
}
}
int main(void) {
char arr[N][STR_LEN];
for(size_t i = 0; i < N; i++) {
if(!fgets(arr[i], STR_LEN, stdin))
break;
strip(arr[i], " \t");
}
for(size_t i = 0; *arr[i]; i++) {
printf("%s", arr[i]);
}
}
Related
I'm trying to count chars from input, and I noticed that while(getchar()!=EOF) produces an extra count, Is it because it counts the null-terminated from input?
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define LINE 5
#define MEM_SIZE 10
char *getInput(int *counter);
void printInput(char *input);
int main() {
char *mainInput;
int counter = 0;
printf("Please enter your input:\n");
mainInput = getInput(&counter);
if (mainInput == NULL) {
return 1;
}
printf("\n\n\nOutput:\n%s\n", mainInput);
printf("number of chars: %d\n", counter);
printInput(mainInput);
free(mainInput);
return 0;
}
char *getInput(int *counter) {
char *p = (char *)malloc(MEM_SIZE * sizeof(char));
char *q = p; /* backup pointer, if realloc fails to allocate, function will return last address values stored */
int c;
int temp_counter = 0;
long current = 0, last = MEM_SIZE - 1;
while ((c = getchar()) != EOF) {
if (current >= last) {
q = p;
p = (char *)realloc(q, last + (MEM_SIZE * sizeof(char)));
if (p == NULL) {
printf("Memory allocation failed, printing only stored values \n");
return q;
}
last += MEM_SIZE;
}
p[current] = c;
temp_counter++;
printf("number of chars: %d\n", temp_counter);
++current;
}
p[current] = '\0';
(*counter) = temp_counter - 1;
return p;
}
void printInput(char *input) {
int i, j = 0;
while (input[j] != '\0') {
for (i = 0; i < LINE; i++) {
if (input[j] == '\0')
break;
putchar(input[j]);
++j;
}
if (input[j] != '\0')
putchar('\n');
}
}
I have a question about the C code for a dynamic 2d char array: malloc buffer overflow. The program idea is to initialize a global 2d char array, when the program is running, type some words, and save them into that 2d char array. I'm not familiar with the realloc function. What is wrong here?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char **array_history;
int count = 0;
#define MAX_LINE_CHARS 1024
int main (void){
array_history = malloc(sizeof(char *));
while (1) {
char line[MAX_LINE_CHARS];
if (fgets(line, MAX_LINE_CHARS, stdin) == NULL)
break;
array_history = realloc(array_history, sizeof(char*)*(count + 1));
int len_size = strlen(line) + 1;
array_history[count] = malloc(len_size*sizeof(char));
for (int i = 0; line[i] != '\0'; i++) {
array_history[count][i] = line[i];
// printf("%c", line[i]);
}
// printf("%s", array_history[0]);
// for (int i = 0; history[i] != NULL; i++) {
// printf("%s\n", history[i]);
// }
count++;
}
for (int i = 0; array_history[i] != NULL; i++) {
printf("%s", array_history[i]);
}
return 0;
}
You have some errors in your code.
You fail to terminate your strings and you fail to add the sentinel value that you are using when printing your string.
A fixed version could look like this:
(You should add more error checking for malloc etc.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MAX_LINE_CHARS 1024
int main (void){
char **array_history;
int count = 0;
array_history = malloc(sizeof(char *)*(count+1));
// TODO: Check for NULL
array_history[0] = NULL; // Terminate the array.
while (1) {
char line[MAX_LINE_CHARS];
if (fgets(line, MAX_LINE_CHARS, stdin) == NULL)
break;
void *temp_ptr = realloc(array_history, sizeof(char*)*(count + 2));
// TODO: Check for NULL
array_history = temp_ptr;
int len_size = strlen(line) + 1;
array_history[count] = malloc(len_size*sizeof(char));
array_history[count + 1] = NULL; // Add sentinel for your array
int i;
for (i = 0; line[i] != '\0'; i++) {
array_history[count][i] = line[i];
// printf("%c", line[i]);
}
array_history[count][i]=0; // Terminate the new string.
// Or simply use strcpy(array_history[count],line);
// printf("%s", array_history[0]);
// for (int i = 0; history[i] != NULL; i++) {
// printf("%s\n", history[i]);
// }
count++;
}
// Instead of terminating NULL value you could just use condition `i<count`
for (int i = 0; array_history[i] != NULL; i++) {
printf("%s", array_history[i]);
}
return 0;
}
I have to read 5 words from the keyboard and put them in a matrix. For example if I have the word RED, the letters will be split between the columns of the first row. R E D and so on.
This is my code but it exits after I scanf 5 letters
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main()
{
char mat[3][3];
for(int i=0; i<2; i++)
for(int j=0;j<2;j++)
{
scanf("%s", &mat[i][j]);
}
for(int i=0; i<2; i++)
for(int j=0;j<2;j++)
{
printf("%s\t",mat[i][j]);
}
return 0;
}
Since you haven't specified any size for the strings... I will presume they are of arbitrary length...
// Takes input using the 'stdin' stream...
char* read_input(void)
{
char ch;
size_t len = 0;
size_t size = len + 2;
char* str = realloc(NULL, size);
if (!str)
return str;
while ((ch = fgetc(stdin)) != -1 && ch != '\n')
{
str[len++] = ch;
if (len == size)
{
str = realloc(str, size += 2);
if (!str)
return str;
}
}
str[len++] = '\0';
return realloc(str, len);
}
This function will read the input, now we also need a function for checking if the string is a valid word... i.e, it contains only alphabets...
// Checks whether the specified string is alphabetic or not...
int is_alpha_string(char* str, char* err_msg)
{
for (unsigned i = 0u; i < strlen(str); i++)
if (!isalpha(str[i]))
{
fprintf(stderr, err_msg);
return 0;
}
return 1;
}
After this, just do:
// The 'main()' function...
int main(void)
{
char* matrix[5];
for (unsigned i = 0u; i < 5u; i++)
{
printf("Enter your word here: ");
matrix[i] = read_input();
i -= !is_alpha_string(matrix[i], "Error! Entered text is not a valid word!\n\n");
}
for (int i = 0; i < 5; i++)
printf("%s\n", matrix[i]);
return 0;
}
Edit: And don't forget to add these includes at the top:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
I am writing a tool to scan all the nodes on a network but I have ran in to a problem. I'm writing the tool in C but I'm new to the language so I'm not sure how the iterate through the address range.
The user will give the argument 192.168.*.* and it will create every IP address in that range, e.g. 192.168.1.1, 192.168.1.2, 192.168.1.3 and then eventually 192.168.2.1, 192.168.2.2, 192.168.2.3 etc.
My previous code was:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void scanner(int s)
{
char addr[20];
for (int i = 0; i < 255; ++i)
{
sprintf(addr, "192.168.%d.%d", s, i);
printf("%s\n", addr);
}
}
int main()
{
for (int i = 0; i < 255; ++i)
{
scanner(i);
}
return 0;
}
But I don't know how to run this from the user input.
You can take the inputs from the user using the scanf function. I have updated your code to use the same -
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int addr_byte_0;
int addr_byte_1;
void scanner(int s)
{
char addr[200];
int i;
for (i = 0; i < 255; ++i)
{
sprintf(addr, "%d.%d.%d.%d", addr_byte_0, addr_byte_1, s, i);
printf("%s\n", addr);
}
}
int main()
{
int i;
//printf("Enter the first byte of the address: ");
scanf ("%d", &addr_byte_0);
//printf("Enter the second byte of the address: ");
scanf ("%d", &addr_byte_1);
for (i = 0; i < 255; ++i)
{
scanner(i);
}
return 0;
}
Also, as per C standards you cannot declare a variable inside the for loop. Hence I have moved the declaration out of the for loop. Hope this helps!
Inspired by (e.g. python-) generators, my solution doesn't perform dynamic memory allocation and and has constant memory consumption. I don't like that I currently rely on a do while loop. Also the explicit check for ig->num_wildcards == 0 is ugly. Anyways:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define IP_OCTETS 4
#define MAX_UCHAR 255
typedef struct {
int wildcard_pos[IP_OCTETS];
int num_wildcards;
int counter[IP_OCTETS];
int octet[IP_OCTETS];
} ip_generator;
char* mystrsep(char** stringp, const char* delim)
{
char* start = *stringp;
char* p;
p = (start != NULL) ? strpbrk(start, delim) : NULL;
if (p == NULL)
{
*stringp = NULL;
}
else
{
*p = '\0';
*stringp = p + 1;
}
return start;
}
void init_ip_gen(ip_generator *ig, char* ip_mask)
{
char *token, *string;
char* ip_mask_ptr = ip_mask;
const char delimiters[] = ".";
int i = 0;
while ((token = mystrsep(&ip_mask_ptr, delimiters)) != NULL)
{
ig->wildcard_pos[i] = -1;
if (strcmp(token, "*") == 0)
{
ig->wildcard_pos[ig->num_wildcards] = i;
ig->counter[ig->num_wildcards] = 1;
ig->num_wildcards++;
}
else
{
ig->octet[i] = atoi(token);
}
i++;
}
}
int ig_next(ip_generator *ig)
{
int i;
int carry = 1;
if (ig->num_wildcards == 0)
{
return 0;
}
for (i = ig->num_wildcards - 1; i >= 0; i--)
{
if (carry == 1)
{
if (ig->counter[i] == MAX_UCHAR)
{
ig->counter[i] = 1;
}
else
{
ig->counter[i]++;
carry = 0;
}
}
if (carry == 0)
{
break;
}
if (i == 0 && carry == 1)
{
return 0;
}
}
return 1;
}
void generate_ip(ip_generator *ig, char *ip)
{
int i;
int j = 0;
int oct[IP_OCTETS];
for (i = 0; i < IP_OCTETS; i++)
{
if (i == ig->wildcard_pos[j])
{
oct[i] = ig->counter[j];
j++;
}
else
{
oct[i] = ig->octet[i];
}
}
sprintf(ip, "%d.%d.%d.%d", oct[0], oct[1], oct[2], oct[3]);
}
int main()
{
char ip_mask[] = "192.*.10.*";
//char ip_mask[] = "192.1.10.123";
ip_generator ig;
memset(&ig, 0, sizeof(ig));
init_ip_gen(&ig, ip_mask);
char ip[32];
memset(ip, 0, sizeof(ip));
do
{
generate_ip(&ig, ip);
printf("%s\n", ip);
} while (ig_next(&ig));
return 0;
}
I have problem with my alignement. This time I want my program to return words that ends and starts with the same letter. I've wrote something like this, but it seems to return random words.
#include <stdio.h>
#include <string.h>
void main()
{
char str[100];
int i, t, j, len;
printf("Enter a string : ");
scanf("%[^\n]s", str);
len = strlen(str);
str[len] = ' ';
for (t = 0, i = 0; i < strlen(str); i++)
{
if ((str[i] == ' ') && (str[i - 1] == str[0]))
{
for (j = t; j < i; j++)
printf("%c", str[j]);
t = i + 1;
printf("\n");
}
else
{
if (str[i] == ' ')
{
t = i + 1;
}
}
}
}
You can use strtok to split the strings from stdin, then apply a letter checker on each parsed word one at a time.
Something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXCHAR 100
int is_start_end(char *word);
void exit_if_null(void *ptr, const char *msg);
int
main(void) {
char str[MAXCHAR];
char *word;
char **all_words;
int words_size = 1, word_count = 0;
int i, found;
all_words = malloc(words_size * sizeof(*all_words));
exit_if_null(all_words, "initial Allocation");
printf("Enter words(enter empty line to terminate):\n");
while (fgets(str, MAXCHAR, stdin) != NULL && strlen(str) != 1) {
word = strtok(str, " \n");
while (word !=NULL) {
if (words_size == word_count) {
words_size *= 2;
all_words = realloc(all_words, words_size * sizeof(*all_words));
exit_if_null(all_words, "Reallocation");
}
all_words[word_count] = malloc(strlen(word)+1);
exit_if_null(all_words[word_count], "Initial Allocation");
strcpy(all_words[word_count], word);
word_count++;
word = strtok(NULL, " \n");
}
}
printf("Words that have equal first and last letters:\n");
found = 0;
for (i = 0; i < word_count; i++) {
if (is_start_end(all_words[i])) {
found = 1;
printf("%s\n", all_words[i]);
}
free(all_words[i]);
all_words[i] = NULL;
}
if (found == 0) {
printf("None Found\n");
}
free(all_words);
all_words = NULL;
return 0;
}
int
is_start_end(char *word) {
int len;
len = strlen(word);
if ((len == 1) || (tolower(word[0]) == tolower(word[len-1]))) {
return 1;
}
return 0;
}
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
This line removes the null terminator of the string:
len = strlen(str);
str[len] = ' ';
thus the string no longer exists, what is left is just an ordinary array of characters.
The next call to strlen, in the body of the for loop, will cause undefined behavior.