I want to get the weight and the object in a list string( in this example I want to get the integer 501 and the string "kg bag of sugar". But I don't know-how may string after the integer. but I do know how many spaces before and after the integer (that is why I do +3 since there are 2 spaces before integer and 1 space at the end). I got a segmentation fault in my code.
Here is an example of what I am trying to do.
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
/* get the weight and the object */
int main(void) {
char line[50] = " 501 kg bag of sugar"; //we don't know how many char after integer
char afterint[50];
long int weight, weight2;
int lenofint;
sscanf(line, "%ld", &weight);
weight2 = weight;
while (weight2 != 0) {
weight2 = weight2 / 10;
lenofint++;
}
afterint[0] = line[lenofint + 3]; // +3 since there are 2 spaces before integer and 1 space at the end
//printf("%c", afterint);
for (int j = 1; j < (strlen(line) - lenofint - 3); j++) {
afterint[j] = afterint[j] + line[j + lenofint + 3];
}
printf("%s", afterint);
}
Stop hard coding offsets and making this hard on yourself. The scanf family of functions includes an option, %n that will tell you how many characters have been processed in the scan up until that point. From there you can skip over whitespace and proceed to the remainder of your label.
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char line[50] = " 501 kg bag of sugger";
long int weight;
int count;
if (sscanf(line, "%ld%n", &weight, &count) == 1)
{
char *suffix = line+count;
while (*suffix && isspace((unsigned char)*suffix))
++suffix;
puts(suffix);
}
}
Output
kg bag of sugger
As a bonus, by using this method you also get error checking. Note the check for return result from sscanf, which indicates the number of successful argument parses. If that isn't 1, it means whatever was in the buffer lead position could not be parsed successfully as %ld (long int), and therefore the rest is pointless.
You can use strtol() to read the number and get a pointer to the point in the string after the number. It would then point to kg bag of sugar. That way you don't need to do any back-calculations from the number. In any case, the number could have leading zeroes or such, so you can't know the length in characters from the numerical value anyway.
Then just skip over the whitespace from the pointer you got from strtol.
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char *foo = " 501 kg bag of sugar";
char *thing = NULL;
int weight = 0;
weight = strtol(foo, &thing, 10);
while (isspace(*thing)) {
item++;
}
printf("weight: %d thing: %s\n", weight, thing);
}
Alternatively, I suppose you could do something like sscanf(foo, "%d %100c", &weight, buffer); to get both the number and the following string. (I'll leave it to you to pick a saner conversion than %100c.)
Related
final.exe file.
this executes infinitely or up to 50.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i;
if (argc < 2)
{
printf("ERROR: You need at least one argument.\n");
return 1;
}
else
{
int i, j;
for(i=1;i<=(int)*argv[1];i++)
{
printf("\n");
(void)system("test1.exe");
}
}
}
test.c file contains :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
printf("Hello World");
}
Expected - For ex. : ./final 2 : The output should be Hello World Hello World , i.e, prints only 2 times and not infinitely.
(int)*argv[1] is using the character code of the first character as the number of iteration. Character codes are usually differ from the number that the character represents.
To convert a string to corresponding number, you can use atoi() (if you don't care about invalid input).
int i, j;
int num = atoi(argv[1]);
for(i=1;i<=num;i++)
{
printf("\n");
(void)system("test1.exe");
}
for(i=1;i<=(int)*argv[1];i++)
The expression (int)*argv[1] uses the first character of the first command line argument (not counting the program name) as a number. That is, assuming an ASCII-like or Unicode-like encoding, the character 0 is treated as value 48, 1 as 49, ..., and 9 as 57. The (int) doesn't really make a difference.
If you really want to use just that first character, you could do something like
if (isdigit(*argv[1])) {
int count = *argv[1] - '0'; // works with any encoding
Or to allow multi-digit counts, you could do something like
char *parse_end;
int count = strtol(argv[1], &parse_end, 10);
if (parse_end != argv[1] && *parse_end == '\0' && count >= 0) {
I'm new to C and am having a lot of issues with arrays that keeps coming up. I'm trying to write a method that takes in a string ("1234") and returns the odd digits, however it keeps printing 49 and I don't know why? Does it have something to do with how I'm assigning the arrays?
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int print_odd_digits(char number[100]) {
int size = sizeof(number[100]);
for (int i = 0; i < size; i++) {
if (number[i] % 2 == 1) {
printf("%d\n", number[i]);
}
}
return 0;
}
int main(void) {
print_odd_digits("1234");
}
sizeof(number[100]) is equivalent to sizeof(char), which is 1. What you want seems strlen(number).
Elements of number are not values of digits but character codes of digits. To convert number characters to values, you can subtract '0'. (character codes for 0 to 9 are defined to be continuous in C).
%d is for printing integer and 49 is ASCII code for the character 1. Use %c to print character corresponding to passed integer.
You may want newline only on end of the characters.
Try this:
#include <stdio.h>
#include <string.h> /* for using strlen() */
int print_odd_digits(char number[100]) {
int size = strlen(number);
for(int i = 0; i < size; i++){
if((number[i] - '0') % 2 == 1){
printf("%c",number[i]);
}
}
printf("\n");
return 0;
}
int main(void) {
print_odd_digits("1234");
}
You have a type error here. You are working with the ascii codes for the text characters for digits. You need to use the atoi(char* str)
function to convert the digits to a corresponding number and use math to determine a particular digit or loop over the characters and subtract -'0' the ascii code for the digit zero as digits are sequential.
#include <stdlib.h>
#include <stdio.h>
int main() {
char* digit_one_str = "1";
char digit_9 = '9';
printf("digit one ascii value: %d\n", digit_one_str[0]); // first char in string digit one
int number_one = atoi(digit_one_str);
printf("digit one parsed from sttring by atoi: %d\n", number_one);
printf("digit 9 as char converted with -'0' trick: %d", (int)(digit_9 - '0'));
}
Further it is better practice to take in a char* and a length than to work with fixed sized arrays or using strlen() where you don't actually have to. In C a string ends in a terminating '\0' character which might not even be present if the code calling your function is buggy or malicious.
I'm trying to get a very large number (more than unsigned long long int). So I get it as a string and then convert it, digit by digit, into integer and use it.
#include <stdio.h>
#include <string.h>
int main()
{
char m[100];
int x;
scanf("%s",m);
for(int i=0; i<strlen(m); i++){
sscanf(m[i],"%d",&x);
printf("%d",x);
}
return 0;
}
However, during compiling it shows:
warning: passing argument 1 of ‘sscanf’ makes pointer from integer
without a cast
and
note: expected ‘const char * restrict’ but argument is of type ‘char’
And, when I run program it will give me the Segmentation fault (core dumped) error.
I also tried more simple code to find the problem:
#include <stdio.h>
#include <string.h>
int main()
{
char m[5];
char n;
int x;
scanf("%s",m);
n = m[1];
sscanf(n,"%d",&x);
return 0;
}
but nothing changed.
scanf doesn't apply to characters. Once you have the characters just convert digits to integers by subtracting '0' as a char:
for(int i=0; i<strlen(m); i++){
x = m[i] - '0'; // line to change
printf("%d",x);
}
Besides, just to make sure that the buffer won't overflow, 100 bytes is good, but you may want to use an according limit in scanf and check the return code:
if (scanf("%99s",m) == 1) {
Using sscanf to convert a single digit of a character string to an integer is the wrong approach. To do this, you only need to subtract the (integer) value of the representation of the character '0' from that digit. Like this:
#include <stdio.h>
#include <string.h>
int main()
{
char m[50]; // As pointed out, a 4-digit number isn't really very long, so let's make it bigger
int x;
scanf("%49s", m); // Limit the input to the length of the buffer!
for (size_t i = 0; i < strlen(m); i++) { // The "strlen" function return "size_t"
x = m[i] - '0'; // The characters `0` thru `9` are GUARANTEED to be sequential!
printf("%d", x);
}
return 0;
}
I am trying to make a program that counts the number of letters that the user has input. When I run my program, it says error: expected ';' after expression on the line count_letters(){ // writing the function to count number of letters? Does a function need a semicolon at the end? I also feel that I am not approaching this problem correctly, can someone please enlighten me :(
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int count_letters(); //function to count letters
int number_of_letters; //length of the string input
int letterCount; // counter for number of letters in the string input
int main(void) {
string text = get_string("Text: "); // getting string input
number_of_letters = strlen(text); //storing the length of string here
printf("Number of letters: %i\n", letterCount); //printing the number of letters in the string input
count_letters() { // writing the function to count number of letters
for (int i = 0; i < number_of_letters; i++) {
if (isalpha(text[i])) {
letterCount++;
}
}
}
}
While you are free to use strlen to get the initial number of characters in text, it isn't necessary. In C, the last character in a "string" is the nul-terminating character '\0' (which has the ASCII value of 0). This is what differentiates a normal array of characters, from a string. It is how all string functions know when to stop scanning for characters.
So you don't need to know beforehand how many characters there are in a string. For example, take the string "hello" entered at the "Text: " prompt where you have declared.
string text = get_string("Text: ");
When you enter "hello" at the prompt:
Text: hello
The string is stored in memory as:
+---+---+---+---+---+---+
| h | e | l | l | o |\0 |
+---+---+---+---+---+---+
^
|
text
where the pointer text points to the address of the first character of the string in memory. Using the fact that a string ends with a nul-terminating character, you can simply scan forward from the start until your reach '\0' (equivalent to plain old 0).
You can use a for loop and iterate using indexes:
for (int i = 0; text[i]; i++)
// do whatever with the character text[i]
Or you can use a pointer and simply increment the pointer so it points to the next character in the string until the '\0' is reached:
string p = text;
while (*p) {
// do whatever with *p (the character at that address)
p++;
}
Putting the last version into your int count_letters (string s) function (that passes a pointer to your string as a parameter to the function) and returns an int representing the number of letters (including only [a-zA-Z]), your function reduces to:
int count_letters (string s)
{
int n = 0;
while (*s) /* while not the nul-character */
if (isalpha (*s++)) /* check if current is letter, advance ptr */
n++; /* increment letter count */
return n; /* return letter count */
}
You main() function, not needing to call strlen() then reduces to:
int main (void) {
string text = get_string ("Text: ");
printf ("Number of letters: %d\n", count_letters(text));
}
Putting it altogether and including the needed headers, you would have:
#include <stdio.h>
#include <ctype.h>
#include "cs50.h"
int count_letters (string s)
{
int n = 0;
while (*s) /* while not the nul-character */
if (isalpha (*s++)) /* check if current is letter, advance ptr */
n++; /* increment letter count */
return n; /* return letter count */
}
int main (void) {
string text = get_string ("Text: ");
printf ("Number of letters: %d\n", count_letters(text));
}
Example Use/Output
Compile and link with the libcs50.so and then, for example you would have:
$ ./bin/ltrcountcs50
Text: hello world
Number of letters: 10
Understanding what a "string" in C is (outside of the unfortunate choice of the typedef char* string; used by CS50), allows you to handle scanning over the characters in your string without needing to know how many characters are included beforehand. (and also helps you understand why failing to provide a nul-terminated string to any of the C string function that expect a nul-terminated string as a parameter results in Undefined Behavior -- they have no way of knowing when to stop scanning for characters).
Look things over and let me know if you have further questions.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int count_letters(); //function to count letters
int number_of_letters; //length of the string input
//initialize letterCount to 0 so that doing letterCount++ does not add 1 to a garbage value
int letterCount = 0; // counter for number of letters in the string input
//define string as a global value if you don't want to refer to it again and again by pass it as parameter or reference
string text;
void count_letters() { //since it's not returning anything, it's void not integer
for(int i = 0; i < number_of_letters; i++) {
if(isalpha(text[i])
letterCount++;
}
}
int main(void){
text = get_string("Text: "); // getting string input
number_of_letters = strlen(text); //storing the length of string here
printf("Number of letters: %i\n", letterCount); //printing the number of letters in the string input
}
Hope this helps. All the comments are there where any modifications are made
I might take your knowledge for being too basic, please forgive me if it is the case.
I believe you have made a small mistake possibly led by the way another language works. The problem lies in the way you have declared count_letters().
To properly declare a function in C, first get out of any existing function, then enter any variable type as a return type for your function, the name of your function, then, in parenthesis, your function's parameters. And after that, your function's code can be inserted between brackets, like you did.
Note you can also declare the function without the code, then put the code for the function lower.
And you might also want to declare your string externally to avoid dealing with pointers.
Here's an example of function declaration:
int foo(int amount)
Hence your code should look a little like this:
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
void count_letters(); //function to count letters
int number_of_letters; //length of the string input
int letterCount; // counter for number of letters in the string input
string text;
int main(void) {
text = get_string("Text: "); // getting string input
number_of_letters = strlen(text); //storing the length of string here
count_letters();
printf("Number of letters: %i\n", letterCount); //printing the number of letters in the string input
}
void count_letters() { // writing the function to count number of letters
for (int i = 0; i < number_of_letters; i++) {
if (isalpha(text[i])) {
letterCount++;
}
}
}
Now please excuse me if I did not understand or answer your question correctly, it would be with pleasure I'd improve myself if I could get more detail. Lacking the cs50.h library, I cannot know for sure my code works.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int count_letters(char *); //function to count letters
int main(void)
{
char* text = get_string("Text: "); // getting string input
printf("Number of letters: %i\n", count_letters(text)); //printing the number of letters in the string input
}
int count_letters(char *text)
{ // writing the function to count number of letters
int letterCount,number_of_letters; //length of the string input
number_of_letters = strlen(text); //storing the length of string here
for(int i = 0; i < number_of_letters; i++){
if(isalpha(text[i]))
{
letterCount++;
}
return letterCount;
}
I am writing a basic C program which will take the input of a string, then convert it to an integer. I am aware of the standard atoi() function, this is purely an exercise I set myself. The code for the program is as follows:
#include <stdio.h>
#include <string.h>
int main (void) {
char input[20];
int counter, temp, magnitude = 0, value = 0;
scanf("%s", input); //takes user input for string to convert
for (counter = strlen(input); counter >= 0; counter--) { //from last to first char of input
temp = input[counter] - '0'; //converts from ASCII to actual value and stores in int
value += temp * magnitude * 10; //temp to correct magnitude and adds to total
magnitude++; //increments magnitude counter
}
printf("%d\n", value); //prints result
return 0;
}
I am trying to iterate backwards from the end of the string, then convert each character to it's actual value from ASCII, then convert it to the correct magnitude, before finally adding it to the final value. It is giving me values which are generally close although wrong.
For example 256 gives 220 and 90 gives 180.
You have two problems. Firstly, you're also trying to convert the terminating NUL byte, which doesn't make sense. Start iterating at strlen(input) - 1.
Second, for the magnitude you want to exponentiate, not multiply, i.e. 10, 100, 1000 rather than 10, 20, 30. For this, you can use pow(), for example:
for (counter = strlen(input) - 1; counter >= 0; counter--) { //from last to first char of input
temp = input[counter] - '0'; //converts from ASCII to actual value and stores in int
value += temp * pow(10, magnitude); //temp to correct magnitude and adds to total
magnitude++; //increments magnitude counter
}
counter = strlen(input)
should be
counter = strlen(input) - 1
so you're using the last valid character of the string.
Two problems here.
1) You should ignore the string null-terminator, so going from strlen(input)-1 will do
2) Your calculation is wrong. You should not multiply by magnitude, but raise 10 to it's power. Or simpler, it itself the required 10's power:
#include <stdio.h>
#include <string.h>
int main (void) {
char input[20];
int counter, temp, magnitude = 1, value = 0;
scanf("%s", input); //takes user input for string to convert
for (counter = strlen(input)-1; counter >= 0; counter--) { //from last to first char of input
temp = input[counter] - '0'; //converts from ASCII to actual value and stores in int
value += temp * magnitude ; //temp to correct magnitude and adds to total
magnitude*=10; //increments magnitude counter
}
printf("%d\n", value); //prints result
return 0;
}
strlen gives the total length of the string. So you have to use
counter = strlen(input)-1
In your for loop. This is because arrays in C start from 0 and end at strlen -1.
While your approach should work (after the issues noted in other answers have been fixed, anyway), it's probably simpler to take this approach:
value = 0;
for (char *p = input; *p; ++p)
value = value * 10 + (*p - '0');
That eliminates a couple unnecessary extra variables, and is probably a bit more efficient. It might not hurt to change the for loop termination condition to *p && isdigit(*p) - that would terminate the conversion on the first non-digit character seen, which might be a desirable approach for dealing with invalid input...
here is a complete answer,
that includes good programming paradigm practices
and defensive coding against user input problems
and results in the right answer
#include <stdio.h> // fgets(), exit(), printf()
#include <stdlib.h> // EXIT_FAILURE, perror()
#include <string.h> // strlen()
#include <ctype.h> // isdigit()
int main () // <-- do not use void
{
char input[20] = {'\0'};
int counter; // index into input array
int value = 0; // initialize the converted int from string
if( NULL != fgets(input, sizeof(input), stdin) )
{ // fgets failed
perror( "fgets failed for string input");
exit( EXIT_FAILURE );
}
// implied else, fgets successful
// note no need to replace trailing '\n' in following code block
for( counter=0; isdigit(input[counter]); counter++)
{
value = value*10 + (input[counter]-'0');
} // end for
printf("the converted value from %s is: %d\n", input, value); //prints result
return 0;
} // end function: main