I know that there is a question with the same name, but it didn't work for me.
I'm making a home-compiler, returns the words that belongs to a language.
The words to analyze are in this vector:
char *cadenas[]= {"123", "4567L", "5a23", '\0'};
Now I want to enter the words by console, but strings can't be used in C, how can I do it? (Without making a matrix possibly)
void getCadenas(char *cadenas[]){
printf("Enter cadenas to be analyzed ('z' to scape) \n \n");
char cadena[15];
gets(cadena);
int x=0;
while(cadena[0]!='z'){
strcpy(cadenas[x],cadena);
x++;
gets(cadena);
}
}
If I understand your problem correctly, you would like the user to be able to enter multiple strings, until he/she types z
See if this piece of code helps you out. The strings will be stored in the cadenas array, as requested.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define MAX_CADENAS 100
#define MAX_CADENA_LEN 255
int getCadenas(char **cadenas){
int x=0;
char cad[MAX_CADENA_LEN+1];
printf("Enter cadenas to be analyzed ('z' to scape) \n \n");
while(x<MAX_CADENAS) {
scanf("%s", cad);
if (strcmp(cad,"z")==0)
break;
cadenas[x] = malloc(strlen(cad)+1);
strcpy(cadenas[x], cad);
x++;
}
return x;
}
char *cadenas[MAX_CADENAS];
int main() {
int num, i;
num = getCadenas(cadenas);
for (i=0;i<num; i++) {
printf("%s\n", cadenas[i]);
}
}
Note0: the code assumes you know in advance what the maximum number of input strings can be (100). It also assumes a maximum size for each input string (255 characters)
Note1: gets is deprecated. Also, instead of scanf, you might want to use fgets.
Note2: the present code is for illustrative purpose only. It allocates memory for each input string, but it assumes no error occurs in doing so (i.e. it does not check what malloc returns).
Note3: the allocated memory blocks must be freed when not used anymore (hint: cycle through the cadenas array and use free)
Assuming you don't mind carrying on with fixed-size strings and arrays, here is your original program modified:
#include <stdio.h>
#include <string.h>
#define MAX_CADENAS 100
#define CADENA_LIMIT 1000
// ...
void getCadenas(char cadenas[MAX_CADENAS][CADENA_LIMIT]){
printf("Enter cadenas to be analyzed ('z' to scape) \n \n");
int x;
for(x=0; x<MAX_CADENAS-1; x++){
char cadena[CADENA_LIMIT];
fgets(cadena, CADENA_LIMIT, stdin);
// fgets will copy the newline character, we don't want that
int cadenaLength=strlen(cadena);
if(cadena[cadenaLength-1]=='\n')
cadena[cadenaLength-1]='\0';
if(strcmp(cadena, "z")==0) break;
strcpy(cadenas[x], cadena);
}
cadenas[x][0]='\0';
}
// ...
Prefer fgets as you can prevent overflow of the fixed-size strings. Unfortunately it copies the newline as well, so I have code to handle that. The result is an array in the form you originally specified (except it ends with "" which we decided was what you were after in the comments).
You can read arbitrary sized strings in C like in other languages, but you would need to implement it with malloc() and co. Allocating dynamically sized memory is primarily controlled with the functions malloc, calloc, realloc and free. This would make the program unavoidably more complicated. Here is one way of doing this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ...
char *getCadena(){
int length=0, capacity=1, character;
char *cadena=malloc(1); // sizeof(char) is always 1
while((character=getchar())!=EOF){
if(character=='\n') break;
// Add character to string
length++;
if(capacity<length){
capacity*=2;
cadena=realloc(cadena,capacity);
}
cadena[length-1]=character;
}
// Add terminator to cadena
length++;
if(capacity<length){
capacity*=2;
cadena=realloc(cadena,capacity);
}
cadena[length-1]='\0';
return cadena;
}
char **getCadenas(){
printf("Enter cadenas to be analyzed ('z' to scape) \n \n");
int length=0, capacity=1;
char **cadenas=malloc(sizeof(char *));
for(;;){
char *cadena=getCadena();
if(strcmp(cadena,"z")==0){
free(cadena);
break;
}
// Add pointer to cadenas array
length++;
if(capacity<length){
capacity*=2;
cadenas=realloc(cadenas,capacity*sizeof(char *));
}
cadenas[length-1]=cadena;
}
// Add NULL to end of cadenas
length++;
if(capacity<length){
capacity*=2;
cadenas=realloc(cadenas,capacity*sizeof(char *));
}
cadenas[length-1]=NULL;
return cadenas;
}
void freeCadenas(char **cadenas){
int i=0;
while(cadenas[i]!=NULL){
free(cadenas[i]);
i++;
}
free(cadenas);
}
// ...
This works mostly the same as the previous function, except you should use freeCadenas eventually, and I end the array with NULL instead of "" which is customary.
The code is a lot longer, but it's pretty typical of more sophisticated C code with less arbitrary limits. In fact real C code usually has more robust handling of errors and more generic functions for managing dynamic arrays. If you actually manage to make this "home-compiler", however, you will figure all this out for yourself.
Related
For example, I want to separate the string "0013subdivision" into 0013 (as an integer that can do addition, subtraction, etc. not char) and subdivision (as a char itself) in the given string.
This is my code so far:
#include <stdio.h>
#include <stdlib.h>
char location[10]; /* for the input with number and letter */
char x;
int house[10]; /* for the integer that will be separated from the string */
int main()
{
printf("Input: ");
scanf ("%s", &location[x]);
x=0
for (x=0; location[x]!='\0'; x++ );
return 0;
}
Based on my research, the code atoi is used to convert the converted value back to int (if I'm not mistaken) but I don't know when to place the function.
location is char array, if you are reading as string use only %s with string name only, index not required.
scanf ("%s", &location[x]); --> scanf ("%s", location);
After separating only int from char array you need to store one int value into house.
int house[10] --> int house.
Here is the code for extracting only int from string :
char location[10]; /* for the input with number and letter */
int x;
int house = 0 ; /* for the integer that will be separated from the string */
int main()
{
printf("Input: ");
//scanf ("%s", &location[x]);
scanf ("%s", location);
for (x=0; location[x]!='\0'; x++ ) {
if(location[x]>='0' && location[x]<='9') {
house =(house * 10) + (location[x]-48);
}
}
printf("int part = %d \n",house);
return 0;
}
The main problem in the code is
scanf ("%s", &location[x]);
Where you did not impose any limit on the scanning. An input like 0013subdivision will cause out of bound memory access leading to undefined behavior.
Always limit the input size with the length modifier, like, for an array defined as
char location[10]
use the conversion specification like
scanf ("%9s", location); // (i) one element saved for terminating null
// (ii) the array name decays to the pointer to 1st element
//in case of an argument to a function call.
Then, you don't need an integer array to store the extracted integer. A singular variable would suffice.
However, i'd like to suggest a much robust way:
read the user input using fgets()
then, scan the input using sscanf() and appropriate conversion specifier, like %4d%9s or alike.
The most correct way to do this is to use the strto... family of functions from stdlib.h. For example:
printf("%ld\n", strtol(str, NULL, 10));
The atoi family of functions should never be used for any purpose, since they have broken error handling and can be 100% replaced by the strto... functions.
You could use the scanf family of functions but they are needlessly slow and notoriously dangerous, so I don't really see the point of using them here.
If you are interested in implementing the actual copying manually, for learning purposes, it is fairly trivial:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main (void)
{
const char str[] = "0013subdivision";
char number_part [sizeof(str)];
char letter_part [sizeof(str)];
size_t i;
for(i=0; str[i]!='\0' && isdigit(str[i]); i++) // find where the letters start
{}
memcpy(number_part, &str[0], i); // copy digit part
number_part[i] = '\0'; // append null terminator
memcpy(letter_part, &str[i], sizeof(str)-i); // copy letter part + null term
puts(number_part);
puts(letter_part);
printf("%ld\n", strtol(str, NULL, 10));
}
If the string is a run-time variable, you have to use strlen(str)+1 instead of sizeof().
strtol converts string to number and also gives you back the character it stopped on, i.e. first character after number.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char* const input = "0013subdivision";
const char* string;
const long number = strtol(input, &string, 10);
printf("Number: %ld String: '%s'\n", number, string);
// Number: 13 String: 'subdivision'
return 0;
}
https://repl.it/repls/SphericalImpracticalTinamou
I am making a console application in C using visualstudio 2015 so that a user can enter the amount of sweets they wish to make and the name of the sweet however there is a problem, the problem is that when the program tries to read a string from the array the program crashes and doesnt print out anything, however if I change it to print a single character using %c it will print out the first character of the string for example if I enter 2 sweets and the strings 'Jawbreaker' and 'Lollipop' It will crash if I use %s for the string however if I use %c for a character it will do its job and print 'J' and 'L' respectively on different lines, Any ideas how I could get this working with the %s specifier for the strings?
The code is below:
#include <stdio.h>
/*Declares the variable needed*/
int sweet_number;
char sweet_name[999];
int main(void) {
/*Prompts the user to enter the number of sweets and saves it to sweet_number*/
printf("Please enter the number of sweets:\n");
scanf("%d", &sweet_number);
/*for loop to enter the name of the sweet into the array*/
for (int i = 0; sweet_number > i; i++) {
printf("What is the name of the sweet?\n");
scanf("%s", &sweet_name[i]);
}
/*Prints array to screen*/
for (int j = 0; sweet_number > j; j++){ /* <- This is where code fails to run*/
printf("%s\n", sweet_name[j]);
}
return 0;
}
You have to use an 2-dimensional array. sweet_name is an array(1-D), each index can store at most one character not a string. Change the following line
char sweet_name[999];
to
char sweet_name[999][100];
OK, I would advice you doing something more efficient and that is to use a double pointer. By doing that, you can solve some problems that the 2D array version has.
The first problem is, what do you do if the user wants to insert more than 999 sweets. Your array can't hold them.
Second, what do you do if the user enters a name that is bigger than 100 characterrs. Again, your 2D array can't hold it. And also, although there is the possibility for the user to enter a name bigger than 100 characters, most users will enter much less than this and now for every string, you have allocated 100 positions when you probably only need about 50. So, let's deal with these problems.
I would probably do something like this:
#include <stdio.h>
#include <string.h> // for strcpy(), strlen()
#include <stdlib.h> // for malloc()
int main(void) {
char **sweet_names; // make a double pointer(or you might see that as array of pointers
char reader[300]; // this variable will help us read every name into the sweet_names
int sweet_number;
int i, j;
// Your code here to get the number of sweet_names
/*Prompts the user to enter the number of sweets and saves it to sweet_number*/
printf("Please enter the number of sweets:\n");
scanf("%d", &sweet_number);
// Now that you know the sweet_number, allocate as much memory as you need.
// And that can be more than 999 sweet names
sweet_names = (char **) malloc(sweet_number * sizeof(char *));
// i.e. make a character pointer to sweet_number character pointers.
// Again, some of your code here
for (i = 0; sweet_number > i; i++) {
printf("What is the name of the sweet?\n");
scanf("%s", reader); // read into the reader
sweet_names[i] = (char *) malloc(strlen(reader) + 1); // allocate as much memory as you need for the current string, the one just read into reader
strcpy(sweet_names[i], reader); // copy contents of reader to sweet_names[i]
}
// Again, your code to print the names
for (j = 0; sweet_number > j; j++){
printf("%s\n", sweet_names[j]);
free(sweet_names[j]); // free every string you allocated, it is good practice
}
// Finally, free the sweet_names pointers. Generally, when you allocate
// dynamically, which is what we do with malloc(), it is a good practice
// to free what you allocate becuase otherwise stays in memory and then
// memory leaks are created. There is a lot to say about C and memory
// but anyway, remember to free
free(sweet_names);
return 0;
}
Finally, now the program again has the limitation to read only names up to 300 characters because of reader, but this is something that you can also deal with, and this is to allocate a crazy amount of memory for reader, like 1000000
characters and then free it.
#include<stdio.h>
#include<ctype.h>
#include<stdbool.h>
#include<string.h>
#define number_of_letters 26
bool IsPangram(char* string);
int main(){
char check[100];
when i put the output as "the quick brown fox jumps over the lazy dog" the output is no a pangram
and when i put a to z values on one single line is gives the correct output
scanf("%s",&check);
if(IsPangram(check)){
printf("the string entered is pangram");
}
else{
printf("not a pangram");
}
return 0;
}
there is the function for pangram
bool IsPangram(char* string){
bool flags[number_of_letters];
int size=strlen(string);
bool ispangram=true;
int i;
char c;
// for all the alfabets to be setting them to false
for(i=0;i<number_of_letters;i++){
flags[i]=false;
}
// for converting the uppper case letter to the small one
for(i=0;i<size;i++){
c=tolower(string[i]);
if(islower(c)){
flags[string[i]-'a']=true;
}
}
// for checking the the lettters to no pangram
for(i=0;(i<number_of_letters && ispangram==true);i++){
if(flags[i]==false){
ispangram=false;
}
}
return ispangram;
}
You don't need use & when passing a string as a char *, since arrays decay to pointers when passed as parameters.
So:
scanf("%s",&check);
should be:
scanf("%s", check);
And some general advice: turn on compiler warnings to help catch simple mistakes such as this, and learn basic debugging techniques (stepping through code in your debugger, adding strategic printf statements, etc).
scanf() with the %s format specifier will stop at whitespace. Try fgets(check,100,stdin) instead... that will read (up to) a full line, and limit the number of characters to 99 + nul so you won't exceed the size of check. It may leave a newline as the last character, but your algorithm would ignore that anyway.
Additionally, in IsPangram(), c should be an int instead of a char (to match tolower() etc.), and change this:
// for converting the uppper case letter to the small one
for(i=0;i<size;i++){
c=tolower(string[i]);
if(islower(c)){
flags[string[i]-'a']=true;
}
}
...to this:
// for converting the uppper case letter to the small one
for(i=0;i<size;i++){
c=tolower(string[i]); /* <== c will always be lowercase */
if(isalpha(c)){ /* <== Check that c is a letter */
flags[c-'a']=true; /* <== use c, as string[i] may be uppercase */
}
}
...for the reasons indicated in the added comments.
scanf cannot get strings with spaces. So use fgets
fgets(check,sizeof(check),stdin);
Or use
scanf("%[^\n]s",check);
This reads a string till a newline character is encountered.
The default scanf stops reading when a space is encountered.
Here you go:
#include <ctype.h>
void uc(char*s){for(;*s;*s=toupper(*s),s++);}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char*argv[])
{int i,j,n=0,c[256]={0};
char*s,*w[1024]={NULL};
do w[n]=malloc(1024),fgets(w[n],1024,stdin),w[n][strlen(w[n])-1]='\0',uc(w[n]),n++;
while(n<1024&&strlen(w[n-1]));
for(--n,i=0;i<n;++i)
for(j=0;j<strlen(w[i]);++j)
c[w[i][j]]=1;
for(j=0,i='A';i<='Z';++i)j+=c[i];
printf("It's %sa pangram\n",j==26?"":"not ");
for(i=0;i<=n;free(w[i++]));}
I know it's possible to use the sizeof function to get the size, but it doesn't get a true count of the array length. If I set an array of int 50 and I stored only 10 numbers in there, I would want to get 10 as the number of elements, but of course that won't happen. I know this is definitely a trivial question, but bear with me here and help me on this if it is possible.
My code so far takes an entire sentence and stores it in an array.
#include <stdio.h>
#include <string.h>
int main()
{
int i=0;
char array[50]={0};
fgets(array, 50, stdin);
int len = sizeof(array); // it doesn't work :((((((
for(i=0; i<len; i++)
{
printf("%c\n", array[i]);
}
return 0;
}
As you guys can see, if the user decides to only enter a word of lets say "Bobby Foo" then I would want len number of 9 including the space, but the sizeof function only gets length of the size of the array declared which is 50.. >.>..
Q: Is it possible to get the number of elements currently stored in an array in C?
Short answer: No. You need to track this information yourself.
You happen to be using fgets() with a character array. Since in this case you're getting a C "string", you can use the C function strlen().
It's worth noting that fgets() will also return a newline - so your string might be a one (Mac, Linux) or two (DOS/Windows) characters longer than you expect.
PS:
Here is a bit more about C strings, including the concept of "null termination" (if you're not already familiar with them):
http://www.cprogramming.com/tutorial/c/lesson9.html
Use strlen to get the size of the array. You need to include string.h.
sizeof() is not a function it is an operator. When sizeof is applied to the name of a static array (not allocated through malloc), the result is the size in bytes of the whole array.
If you are using fgets, then you need to remove \n from the string. A simple way would be:
array[strlen(array) - 1] = '\0';
A quick example:
#include <stdio.h>
#include <string.h>
#include <stddef.h>
int main()
{
int i=0;
char array[50]={0};
char *p;
fgets(array, 50, stdin);
//Remove `\n` from the array.
if ((p=strchr(array, '\n')) != NULL)
*p = '\0';
size_t len = strlen(array); // Use strlen to find the length of string
for(i=0; i<len; i++)
{
printf("%c\n", array[i]);
}
return 0;
}
I am currently learning C, and so I wanted to make a program that asks the user to input a string and to output the number of characters that were entered, the code compiles fine, when I enter just 1 character it does fine, but when I enter 2 or more characters, no matter what number of character I enter, it will always say there is just one character and crashes after that. This is my code and I can't figure out what is wrong.
int main(void)
{
int siz;
char i[] = "";
printf("Enter a string.\n");
scanf("%s", i);
siz = sizeof(i)/sizeof(char);
printf("%d", siz);
getch();
return 0;
}
I am currently learning to program, so if there is a way to do it using the same scanf() function I will appreciate that since I haven't learned how to use any other function and probably won't understand how it works.
Please, FORGET that scanf exists. The problem you are running into, whilst caused mostly by your understandable inexperience, will continue to BITE you even when you have experience - until you stop.
Here is why:
scanf will read the input, and put the result in the char buffer you provided. However, it will make no check to make sure there is enough space. If it needs more space than you provided, it will overwrite other memory locations - often with disastrous consequences.
A safer method uses fgets - this is a function that does broadly the same thing as scanf, but it will only read in as many characters as you created space for (or: as you say you created space for).
Other observation: sizeof can only evaluate the size known at compile time : the number of bytes taken by a primitive type (int, double, etc) or size of a fixed array (like int i[100];). It cannot be used to determine the size during the program (if the "size" is a thing that changes).
Your program would look like this:
#include <stdio.h>
#include <string.h>
#define BUFLEN 100 // your buffer length
int main(void) // <<< for correctness, include 'void'
{
int siz;
char i[BUFLEN]; // <<< now you have space for a 99 character string plus the '\0'
printf("Enter a string.\n");
fgets(i, BUFLEN, stdin); // read the input, copy the first BUFLEN characters to i
siz = sizeof(i)/sizeof(char); // it turns out that this will give you the answer BUFLEN
// probably not what you wanted. 'sizeof' gives size of array in
// this case, not size of string
// also not
siz = strlen(i) - 1; // strlen is a function that is declared in string.h
// it produces the string length
// subtract 1 if you don't want to count \n
printf("The string length is %d\n", siz); // don't just print the number, say what it is
// and end with a newline: \n
printf("hit <return> to exit program\n"); // tell user what to do next!
getc(stdin);
return 0;
}
I hope this helps.
update you asked the reasonable follow-up question: "how do I know the string was too long".
See this code snippet for inspiration:
#include <stdio.h>
#include <string.h>
#define N 50
int main(void) {
char a[N];
char *b;
printf("enter a string:\n");
b = fgets(a, N, stdin);
if(b == NULL) {
printf("an error occurred reading input!\n"); // can't think how this would happen...
return 0;
}
if (strlen(a) == N-1 && a[N-2] != '\n') { // used all space, didn't get to end of line
printf("string is too long!\n");
}
else {
printf("The string is %s which is %d characters long\n", a, strlen(a)-1); // all went according to plan
}
}
Remember that when you have space for N characters, the last character (at location N-1) must be a '\0' and since fgets includes the '\n' the largest string you can input is really N-2 characters long.
This line:
char i[] = "";
is equivalent to:
char i[1] = {'\0'};
The array i has only one element, the program crashes because of buffer overflow.
I suggest you using fgets() to replace scanf() like this:
#include <stdio.h>
#define MAX_LEN 1024
int main(void)
{
char line[MAX_LEN];
if (fgets(line, sizeof(line), stdin) != NULL)
printf("%zu\n", strlen(line) - 1);
return 0;
}
The length is decremented by 1 because fgets() would store the new line character at the end.
The problem is here:
char i[] = "";
You are essentially creating a char array with a size of 1 due to setting it equal to "";
Instead, use a buffer with a larger size:
char i[128]; /* You can also malloc space if you desire. */
scanf("%s", i);
See the link below to a similar question if you want to include spaces in your input string. There is also some good input there regarding scanf alternatives.
How do you allow spaces to be entered using scanf?
That's because char i[] = ""; is actually an one element array.
Strings in C are stored as the text which ends with \0 (char of value 0). You should use bigger buffer as others said, for example:
char i[100];
scanf("%s", i);
Then, when calculating length of this string you need to search for the \0 char.
int length = 0;
while (i[length] != '\0')
{
length++;
}
After running this code length contains length of the specified input.
You need to allocate space where it will put the input data. In your program, you can allocate space like:
char i[] = " ";
Which will be ok. But, using malloc is better. Check out the man pages.