I am having trouble storing strings into a 2d array using scanf.
To illustrate, this is the input the program accepts:
p2/src/stuff:5:
p3/src/stuff:5:
p4/src/stuff:6:
So I want to be able to split the strings and numbers by colons and store them separately. So ideally, my 2d array would look like this for strings:
[["p2/src/stuff"], ["p3/src/stuff"], ["p4/src/stuff"]]
Numbers can be stored in a 1d array.
Here is what I have so far:
int main() {
char *str;
char *i;
int n = 1;
while (n == 1) {
n = scanf("%m[^':']:%m[^':']:", &str, &i);
}
printf("# inputs read: %d\n", n);
printf("%s\n", str);
printf("%s\n", i);
}
Here it only prints the first line:
p2/src/stuff
5
Should I have an iterator that dose pointer arithmetic? I'm not familiar with pointer arithmetic.
scanf returns the number of items scanned. In this case it would be 2 instead of 1. Here a return of 1 would indicate a problem during the scan.
The %m specifier allocates memory to the pointers. Using a single pair of pointers, they should be freed in eadh iteration of the loop. You could use an array of pointers to store each of the inputs.
The scanset does not need the single quotes [^':']. If you are scanning for all characters that are not a colon [^:] will work.
EOF will terminate the while loop so if you are reading from a file, it will stop at the end of the file. Reading from stdin could be terminated using Ctrl+D (Linux) or Ctrl+Z (Windows).
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char *str;
char *i;
int n;
while ( ( n = scanf("%m[^:]:%m[^:]:", &str, &i)) == 2) {
printf("# inputs read: %d\n", n);
printf("%s\n", str);
printf("%s\n", i);
free ( str);
free ( i);
}
return 0;
}
EDIT:
This uses an array of pointers to collect several inputs to the str and i arrays.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char *str[10];// array of pointers
char *i[10];
int each = 0;
int loop = 0;
int n = 0;
while ( ( n = scanf("%m[^:]:%m[^:]:", &str[each], &i[each])) == 2) {
printf("# inputs read: %d\n", n);
printf("%s\n", str[each]);
printf("%s\n", i[each]);
each++;
if ( each > 9) {
break;//too many inputs for array size
}
}
for ( loop = 0; loop < each; loop++) {
printf ( "str[%d]=%s\n", loop, str[loop]);//print all the str inputs
}
for ( loop = 0; loop < each; loop++) {
printf ( "i[%d]=%s\n", loop, i[loop]);//print all the i inputs
}
for ( loop = 0; loop < each; loop++) {//free memory
free ( str[loop]);
free ( i[loop]);
}
return 0;
}
You have a few issues here.
First, while you should be using character pointers, you never allocate any memory for them. Next, when you use scanf, you should not be passing the address of the pointers but the pointers themselves. This is an easy mistake to make since you must pass the address when using scanf with integer types.
int main() {
char str[255];
char i[255];
int n = 1;
while (n == 1) {
n = scanf("%m[^':']:%m[^':']:", str, i);
}
printf("# inputs read: %d\n", n);
printf("%s\n", str);
printf("%s\n", i);
}
Related
#include <Stdio.h>
#include <string.h>
int main(){
char str[51];
int k = 1;
printf("Enter string\n");
scanf("%s", &str);
for(int i = 0; i < strlen(str); i++){
while(str[k] != '\0')){
if(str[i] == str[k]){
printf("%c", str[i]);
k++;
}
}
}
return 0;
}
It is simple C code that checks for duplicate characters in string and prints the characters. I am not understanding why it is producing an infinite loop. The inner while loop should stop when str[k] reaches the null terminator but the program continues infinitely.
Points to know
You don't need to pass the address of the variable str to scanf()
Don't use "%s", use "%<WIDTH>s", to avoid buffer-overflow
Always check whether scanf() conversion was successful or not, by checking its return value
Always use size_t to iterator over any array
i < strlen(str), makes the loop's time complexity O(n3), instead of O(n2), which also isn't very good you should check whether str[i] != 0. But, many modern compilers of C will optimize it by the way.
#include <Stdio.h> it is very wrong, stdio.h != Stdio.h
Call to printf() can be optimized using puts() and putc() without any special formatting, here also modern compiler can optimize it
while(str[k] != '\0')){ has a bracket (')')
Initialize your variable str using {}, this will assign 0 to all the elements of str
Better Implementation
My implementation for this problem is that create a list of character (256 max) with 0 initialized, and then add 1 to ASCII value of the character (from str) in that list. After that print those character whose value was greater than 1.
Time Complexity = O(n), where n is the length of the string
Space Complexity = O(NO_OF_CHARACTERS), where NO_OF_CHARACTERS is 256
Final Code
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
static void print_dup(const char *str)
{
size_t *count = calloc(1 << CHAR_BIT, sizeof(size_t));
for(size_t i = 0; str[i]; i++)
{
count[(unsigned char)str[i]]++;
}
for (size_t i = 0; i < (1 << CHAR_BIT); i++)
{
if(count[i] > 1)
{
printf("`%c`, count = %zu\n", i, count[i]);
}
}
free(count);
}
int main(void) {
char str[51] = {};
puts("Enter string:");
if (scanf("%50s", str) != 1)
{
perror("bad input");
return EXIT_FAILURE;
}
print_dup(str);
return EXIT_SUCCESS;
}
Read your code in English: You only increment variable k if character at index k is equal to character at index i. For any string that has different first two characters you will encounter infinite loop: char at index i==0 is not equal to char at index k==1, so k is not incremented and while(str[k]!=0) loops forever.
the objective of my question is very simple. The first input that I get from the user is n (number of test cases). For each test case, the program will scan a string input from the user. And each of these strings I will process separately.
The question here is how can I get string inputs and process them separately in C language??? The idea is similar to the dictionary concept where we can have many words which are individual arrays inside one big array.
The program I have written so far:
#include <stdio.h>
#define max 100
int main (){
int n; // number of testcases
char str [100];
scanf ("%d\n",&n);
for (int i =0;i <n;i++){
scanf ("%s",&str [i]);
}
getchar ();
return 0;
}
Can someone suggest what should be done?
The input should be something like this:
Input 1:
3
Shoe
Horse
House
Input 2:
2
Flower
Bee
here 3 and 2 are the values of n, the number of test cases.
First of all, Don't be confused between "string" in C++ , and "Character Array" in C.
Since your question is based on C language, I will be answering according to that...
#include <stdio.h>
int main (){
int n; // number of testcases
char str [100][100] ; // many words , as individual arrays inside one big array
scanf ("%d\n",&n);
for (int i =0;i <n;i++){
scanf ("%s",str[i]); // since you are taking string , not character
}
// Now if you want to access i'th word you can do like
for(int i = 0 ; i < n; i++)
printf("%s\n" , str[i]);
getchar ();
return 0;
}
Now here instead of using a two-dimensional array, you can also use a one-dimensional array and separate two words by spaces, and store each word's starting position in some another array. (which is lot of implementation).
First of all yours is not C program, as you can't declare variable inside FOR loop in C, secondly have created a prototype using Pointer to Pointer, storing character array in matrix style datastructure, here is the code :-
#include <stdio.h>
#include <stdlib.h>
#define max 100
int main (){
int n,i; // number of testcases
char str [100];
char **strArray;
scanf ("%d",&n);
strArray = (char **) malloc(n);
for (i =0;i <n;i++){
(strArray)[i] = (char *) malloc(sizeof(char)*100);
scanf ("%s",(strArray)[i]);
}
for (i =0;i <n;i++){
printf("%s\n",(strArray)[i]);
free((strArray)[i]);
}
getchar ();
return 0;
}
#include <stdio.h>
#define MAX 100 // poorly named
int n=0; // number of testcases
char** strs=0;
void releaseMemory() // don't forget to release memory when done
{
int counter; // a better name
if (strs != 0)
{
for (counter=0; counter<n; counter++)
{
if (strs[counter] != 0)
free(strs[counter]);
}
free(strs);
}
}
int main ()
{
int counter; // a better name
scanf("%d\n",&n);
strs = (char**) calloc(n,sizeof(char*));
if (strs == 0)
{
printf("outer allocation failed!")
return -1;
}
for (counter=0; counter<n; counter++)
{
strs[counter] = (char*) malloc(MAX*sizeof(char));
if (strs[counter] == 0)
{
printf("allocate buffer %d failed!",counter)
releaseMemory();
return -1;
}
scanf("%s",&strs[counter]); // better hope the input is less than MAX!!
// N.B. - this doesn't limit input to one word, use validation to handle that
}
getchar();
// do whatever you need to with the data
releaseMemory();
return 0;
}
I have I problem. I get 2 warnings from console, but I dont know what's wrong with my code. Can you have look?
Program suppose to show lines with at least 11 characters and 4 numbers
#include <stdio.h>
#include <ctype.h>
int main()
{
char line[200];
printf("Enter a string: \n");
while(fgets(line, sizeof(line),stdin))
{
int numberAlpha = 0;
int numberDigit = 0;
if(isalpha(line)) numberAlpha++;
else if(isdigit(line)) numberDigit++;
if(numberAlpha+numberDigit>10 && numberDigit>3) printf("%s \n", line);
}
return 0;
}
Both isalpha() and isdigit() takes an int, not a char *, as argument.
In your code, by passing the array name as the argument, you're essentially passing a char * (array name decays to the pointer to the first element when used as function argument), so, you're getting the warning.
You need to loop over the individual elements of line and pass them to the functions.
That said, just a suggestion, for hosted environment, int main() should be int main(void) to conform to the standard.
isalpha and isdigit are supposed to test if a char taken as int (a char can be safely converted to an int) is the encoding of an alphanumeric or digit character. You pass a char array, not an individual char. You need to test each char of the string you got, so you need a loop as:
for (int i=0; i<strlen(line); i++) {
if (isalpha(line[i])) numberAlpha++;
...
}
It is better to compute the length once:
int length = strlen(line);
for (int i=0; i<length; i++) {
...
}
You may also use a pointer to move along the string:
for (char *ptr = line; *ptr!=`\0`; ptr++) {
if (isalpha(*ptr)) ...
...
}
isalpha() and isdigit() functions take an int. But you are passing a char* i.e. the array line gets converted into a pointer to its first element (see: What is array decaying?). That's what the compiler complains about. You need to loop over line to find the number of digits and alphabets in it.
Also note that fgets() will read in the newline character if line has space. So, you need to trim it out before counting.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void)
{
char line[200];
printf("Enter a string: \n");
while(fgets(line, sizeof(line),stdin))
{
int numberAlpha = 0;
int numberDigit = 0;
line[strcspn(line, "\n")] = 0; // Remove the trailing newline, if any.
for (size_t i = 0; line[i]; i++) {
if(isalpha((unsigned char)line[i])) numberAlpha++;
else if((unsigned char)isdigit(line[i])) numberDigit++;
}
printf("alpha: %d, digits:%d \n", numberAlpha, numberDigit);
}
return 0;
}
Ok, i got something like this:
#include <stdio.h>
#include <ctype.h>
int main()
{
char line[200];
printf("Enter a string: \n");
while(fgets(line, sizeof(line),stdin))
{
int numberAlpha = 0;
int numberDigit = 0;
int i;
for(i=0; i<strlen(line); i++){
if(isalpha(line[i])) numberAlpha++;
else if(isdigit(line[i])) numberDigit++;
}
if(numberAlpha+numberDigit>10 && numberDigit>3) printf("%s \n", line);
}
return 0;
}
Now the question is, if it is passible to make it first accepts data and then display only those line which follows the if statment. Now it shows line just after input it.
I am not very experienced in C. I am trying to have some code that works like this:
Declare array of strings;
Function that erases array of strings
and inserts a new set of strings (number unknown)
How can I do this? I know I can do const char *a[2]; but that requires entering an array size when I declare it. Can I make a variable for my string array that can support multiple sizes?
You can use pointers to pointers.
char **strings;
Here is how you would create it: (where <size> is the size of the array)
strings = malloc(sizeof(char*) * <size>);
Now setting/getting elements is pretty simple:
strings[0] = "hello";
printf("%s", strings[0]);
Just a warning, the memory is not already set to fully null strings. If you want all of the strings to be empty by default then use calloc() instead of malloc():
strings = calloc(sizeof(char*) , <size>);
You can control array size like this:
int size;
char *a[size];
printf("enter size");
scanf("%d",&size);
You have to use a char**, a pointer to pointer to char, to by able to capture a dynamic array of strings.
If you want 10 strings, you have to use:
char** strings = (char**)malloc(sizeof(char*)*10);
To store a string in the first element of the array, you have to use:
strings[0] = malloc(strlen("abcd")+1);
strpcy(strings[0], "abcd");
Here's a program that demonstrates the whole thing:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char string[200];
char** strings = NULL;
int numStrings = 0;
int n = 0;
int i = 0;
/* Read the number of strings */
do
{
printf("Enter the number of strings (0 or higher): ");
n = scanf("%d", &numStrings);
} while ( n != 1 || numStrings < 0 );
/* Eat up the remaining characters afte the integer */
fgets(string, 199, stdin);
if ( numStrings > 0 )
{
/* Read the strings */
strings = (char**)malloc(numStrings*sizeof(char*));
for ( i = 0; i != numStrings; ++i )
{
printf("Enter a string: ");
fgets(string, 199, stdin);
strings[i] = malloc(strlen(string)+1);
strcpy(strings[i], string);
}
/* Print the strings back */
for ( i = 0; i != numStrings; ++i )
{
printf("%s", strings[i]);
}
/* Now release the memory back to the system */
/* First the individual strings */
for ( i = 0; i != numStrings; ++i )
{
free(strings[i]);
}
/* Now the array */
free(strings);
}
return 0;
}
So after a few years of inactivity after studying at uni, I'm trying to build up my c experience with a simple string reverser.
here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
*
*/
int main(int argc, char** argv) {
reverser();
return(0);
}
int reverser(){
printf("Please enter a String: ");
//return (0);
int len;
char input[10];
scanf("%s",&input);
int quit = strcmp(input,"quit");
if(quit == 0){
printf("%s\n","Program quitting");
return(0);
}
len = strlen(input);
printf("%i\n",len);
char reversed[len];
int count = 0;
while (count <= (len-1)){
//printf("%i\n",(len-count));
reversed[count] = input[(len-1)-count];
count++;
}
//printf("%s\n",input);
printf(reversed);
printf("\n");
reverser();
}
When I input "hello", you would expect "olleh" as the response, but I get "olleh:$a ca&#",
How do I just get the string input reversed and returned?
Bombalur
Add a '\0' at the end of the array. (as in, copy only chars until you reach '\0' - which is the point at array[strlen(array)], then when you're done, add a '\0' at the next character)
Strings are conventionally terminated by a zero byte. So it should be
char reversed[len+1];
And you should clear the last byte
reversed[len] = (char)0;
you forgot the \0 at the end of the string
This is because you are creating an array with size 10. When you take in some data into it (using scanf) and the array is not filled up completely, the printf from this array will give junk values in the memory. You should iterate for the length of the input by checking \n.
must have a size + 1 to string length so that you can have a \0 at the end of string that will solve your problem
The following is a (simple and minimal implementation of) string reverse program (obviously, error conditions, corner cases, blank spaces, wider character sets, etc has not been considered).
#include <stdio.h>
int strlen(char *s)
{
char *p = s;
while (*p)
p++;
return p - s;
}
char * strrev(char a[])
{
int i, j;
char temp;
for (i=0, j=strlen(a)-1 ; i<j ; i++, j--) {
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
return a;
}
int main()
{
char str[100];
printf("Enter string: ");
scanf("%s", str);
printf("The reverse is %s \n", strrev(str));
return 0;
}
Hope this helps!