In C, how do I check if a string read from a file contains a 10 digit number. I have used strspn and it seems to work, but I think there are better ways. Any help greatly appreciated.
char cset[] = "1234567890";
do
{
// read line into line_string
} while (strspn(line_string, cset) != 10);
It should work. Are you sure you read the line_string correctly?
char cset[] = "1234567890";
char line[] = "9846578497";
printf("%d", strspn(line, cset));
outputs 10. A simple loop that explicitly checks every character is quite straightforward too:
int i, digits = 0;
for (i = 0; line[i] != '\0'; ++i) // <-- make sure line is null-terminated
if (isdigit(line[i])) digits++;
printf("%d", digits);
There's a much eaiser way, use the string.h library
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
char string[] = "0123456789";
int stringLength = strlen(string);
printf("%d\n", stringLength);
return 0;
}
It depends on what you wanted.
Let's presume a bunch of different inputs. For that we have:
char cset[] = "1234567890";
char str1[] = "5319764208"; /* all digits in different order */
strspn(str1, cset); /* returns 10 */
char str2[] = "098765432"; /* not all digits present */
strspn(str2, cset); /* returns 9 */
char str3[] = "not098a7654num321"; /* not a number, but has all digits */
strspn(str3, cset); /* returns 0 */
char str4[] = "blah 1234567890 blah"; /* all digits in same order plus chars */
strspn(str4, cset); /* returns 0 */
So it depends on what you intended acceptable input to be.
Yes there are many efficient ways but it depends how you are going to use them in your program. There are commands depending on your context of use, you can read on "strncmp" and "strstr".
If you want to compare for string in the starting of the line you can use,strncmp here is the example.
#define VALID_STRING " <project"
#define COMPARELIMIT 10
if(!strncmp(linebuffer, VALID_STRING, COMPARELIMIT)) {
// your code goes here
}
else {
}
if you want to compare at any other point in the line buffer use "strstr"
#define CHECK_STRING "name="
char *start=NULL;
start=strstr(linebuffer, CHECK_STRING);
// it returns the address pointing to the first character of that(CHECK_STRING) string any where in linebuffer.
Related
I'm still a newbie to C so please forgive me if anything below is wrong. I've searched this up online but nothing really helped.
Right now, I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void appendStr (char *str, char c)
{
for (;*str;str++); // note the terminating semicolon here.
*str++ = c;
*str++ = 0;
}
int main(){
char string[] = "imtryingmybest";
char result[] = "";
for(int i = 0; i < strlen(string); i++){
if(i >= 0 && i <= 3){
appendStr(result, string[i]);
}
}
printf("%s", result);
}
Basically, I'm trying to add the first 4 characters of the String named string to result with a for loop. My code above did not work. I've already tried to use strcat and strncat and neither of them worked for me either. When I used
strcat(result, string[i]);
It returns an error saying that the memory cannot be read.
I know that in this example it might have been easier if I just did
appendStr(result, string[0]);
appendStr(result, string[1]);
appendStr(result, string[2]);
appendStr(result, string[3]);
But there is a reason behind why I'm using a for loop that couldn't be explained in this example.
All in all, I'd appreciate it if someone could explain to me how to append individual characters to a string in a for loop.
The following code doesnt use your methods but successfully appends the first 4 chars to result
#include <stdio.h>
#include <string.h>
int main()
{
// declare and initialize strings
char str[] = "imtryingmybest";
char result[5]; // the 5th slot is for \0 as all strings are null terminated
// append chars to result
strncat(result, str, 4);
// ^ ^ ^
// | | |- number of chars to be appended
// | | - string to be appended from
// | - string to append to
// print string
printf("result: %s\n", result);
return (0);
}
The result of the above is as wanted:
>> gcc -o test test.c
>> ./test
result: imtr
Let me know if anything is not clear so i can elaborate further
string was ruined by the overflow of result buffer.
appendStr can be executed only once. next time strlen(string) will return 0. because *str++ = 0; has been written to the space of string.
result buffer has only 1 byte space, but you write 2 byte to it in appendStr call.
the second byte will ruin string space.
I suggest debug with gdb.
try to get rid of Magic numbers
#define BUFF_SIZE 10 // define some bytes to allocate in result char array
#define COPY_COUNT 4 // count of chars that will be copied
int main(){
char string[] = "imtryingmybest";
char result[BUFF_SIZE] {}; // allocate some chunk of memory
for(size_t i = 0; i < strlen(string); i++){
if(i < COPY_COUNT){
appendStr(result, string[i]);
}
}
printf("%s", result);
}
I showed the solution code Paul Yang showed the problem
As others have pointed out the code has a simple mistake in the allocation of the destination string.
When declaring an array without specifying its size, the compiler deduces it by its initializer, which in your case means a 0 + the NULL character.
char result[] = ""; // means { '\0' };
However, I think that the bigger issue here is that you're effectively coding a Schlemiel.
C strings have the serious drawback that they don't store their length, making functions that have to reach the end of the string linear in time complexity O(n).
You already know this, as shown by your function appendStr()
This isn't a serious issue until start you appending characters or strings in a loop.
In each iteration of your loop appendStr() reaches the last character of the string, and extends the string, making the next iteration a little slower.
In fact its time complexity is O(n²)
Of course this is not noticeable for small strings or loops with few iterations, but it'll become a problem if the data scales.
To avoid this you have to take into account the growing size of the string.
I modified appendStr() to show that now it starts from the last element of result
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void appendStr (char *str, char c, char *orig)
{
printf("i: %ld\n", str - orig);
for (; *str; str++); // note the terminating semicolon here.
*str++ = c;
*str++ = 0;
}
int main()
{
char string[32] = "imtryingmybest";
char result[32] = "";
for(int i = 0; i < strlen(string); i++) {
if(i >= 0 && i <= 3) {
// I'm passing a pointer to the last element of the string
appendStr(&result[i], string[i], result);
}
}
printf("%s", result);
}
You can run it here https://onlinegdb.com/HkogMxbG_
More on Schlemiel the painter
https://www.joelonsoftware.com/2001/12/11/back-to-basics/
https://codepen.io/JoshuaVB/pen/JzRoyp
I'm new to C (and programming) and it's possible that my question can be answered with some basic searching and reading; please point me to an answer to the question if it exists.
Let's say that I want to read a number that can possibly be above 999 from the user. From my experience, if I enter the value 10,000 (including the comma), the program would read the number until the comma and then stop taking input. Thus, the input would be 10 instead of 10000.
How can I make it read '10,000' as if it is 10000?
#include <stdio.h>
#include <stdlib.h>
void RemoveChar(char* Number, char chartoberemoved)
{
char *p, *s;
p = s = Number;
while (*s)//Run until last \r\n
{
if (*s != chartoberemoved)
{
*p++ = *s;
}
/* We always advance s. */
s++;
}
/* We 0-terminate p. */
*p = 0;
}
int main(int argc, char* argv[])
{
char array[32];
if (!argv[1])
return -1;
strcpy(array, argv[1]);
RemoveChar(array, ',');
int num = atoi(array);
printf("%d\n", num);
return 0;
}
Most implementation of scanf and printf on Linux support ' to tell that the number may have a thousands separator:
#include <stdio.h>
#include <locale.h>
int main(int argc, char const *argv[])
{
setlocale(LC_NUMERIC, ""); // set the locale so that "," is a thousands separator
const char* string = "10,000";
float num = 0;
sscanf(string, "%'f", &num);
printf("%f\n", num);
return 0;
}
returns
10000.000000
https://www.systutorials.com/docs/linux/man/3-printf/
use strtok its information and documentation can be found here. link
I want to print a line similar as following:
====================================
And I need to control the count of the char, and able to specify which char to print.
I don't want to use loop.
Is it possible to do this with a single printf() statement?
#Update
I ask this because I use printf in this way sometimes:
printf("%10s\n", "abc");
So, if printf could do this, then it's possible to do what I ask, I am just not sure ... now I know it can't ...
Ok, I wrote a simple util function to do this:
#include <stdio.h>
void printRepeatChar(char c, int count) {
char cs[count+1];
int i;
for(i=0; i<count; i++)
cs[i] = c;
cs[count] = '\0';
printf("%s\n", cs);
}
int main(int argc, char * argv[]) {
printRepeatChar('-', 6*4);
}
maybe use memset() from string.h instead of the direct loop makes the code shorter, just as in the answers.
And, thank you all for help.
#include <stdio.h>
#include <string.h>
void PrintStuff( char to_print, int length ) {
// adjust buffer size as desired
char buffer[256];
// -1 for null terminator
if( length > sizeof(buffer)-1 ) length = sizeof(buffer)-1;
// fill buffer with desired character
memset( buffer, to_print, length );
// add null terminator
buffer[length] = 0;
// print to output
puts( buffer );
}
int main() {
PrintStuff( '=', 11 );
return 0;
}
http://ideone.com/RjPr83
And to answer the subquestion: no, printf cannot repeat a character as a formatting rule. It can only repeat spaces or 0's when padding.
#include <stdio.h>
#include <string.h>
int main(void) {
char c='=';
char a[20];
memset(a,c,(sizeof(a)-1));
a[19] = '\0';
printf("%s\n",a);
return 0;
}
Dynamic memory allocation and character scanning can be added to this .
It's not something trivial but I would like to know the best way to process multiple outputs, for example:
Input
First line of input will contain a number T = number of test cases. Following lines will contain a string each.
Output
For each string, print on a single line, "UNIQUE" - if the characters are all unique, else print "NOT UNIQUE"
Sample Input
3
DELHI
london
#include<iostream>
Sample Output
UNIQUE
NOT UNIQUE
NOT UNIQUE
So how can I accomplish outputs like that? My code so far is:
int main(int argc, char *argv[])
{
int inputs, count=0;
char str[100];
char *ptr;
scanf("%d",&inputs);
while(inputs-- >0)
{
scanf("%s",str);
for(ptr=str; *ptr!='\0';ptr++)
{
if( *ptr== *(ptr+1))
{
count++;
}
}
if(count>0)
{
printf("NOT UNIQUE");
}
else
{
printf("UNIQUE");
}
}
}
But the above will obviously print the output after each input, but I want the output only after entering all the inputs, if the user enters 3, then the user have to give 3 strings and after the output will be given whether the given strings are unique or not. So I want to know how can I achieve the result given in the problem. Also another thing I want to know is, I am using an array of 100 char, which it can hold a string up to 100 characters, but what do I have to do if I want to handle string with no limit? Just declaring char *str is no good, so what to do?
Hope this helps:
#include <stdio.h>
int main(int argc, char *argv[])
{
int inputs,count=0;
char str[20];
scanf("%d",&inputs);
char *ptr;
char *dummy;
while(inputs-- >0)
{
scanf("%s",str);
for(ptr=str; *ptr!='\0';ptr++)
{
for(dummy=ptr+1; *dummy != '\0';dummy++)
{
if( *ptr== *dummy)
{
count=1;
}
}
if(count == 1)
break;
}
if(count>0)
{
printf("NOT UNIQUE");
}
else
{
printf("UNIQUE");
}
}
}
If you want to save stuff for later use, you must store it somewhere. The example below stores up to 10 lines in buf and then points str to the current line:
#include <stdlib.h>
#include <stdio.h>
#include <string.h> /* for strlen */
#include <ctype.h> /* for isspace */
int main(int argc, char *argv[])
{
int ninput = 0;
char buf[10][100]; /* storage for 10 strings */
char *str; /* pointer to current string */
int i;
printf("Enter up to 10 strings, blank to and input:\n");
for (i = 0; i < 10; i++) {
int l;
str = buf[i];
/* read line and break on end-of-file (^D) */
if (fgets(str, 100, stdin) == NULL) break;
/* delete trailing newline & spaces */
l = strlen(str);
while (l > 0 && isspace(str[l - 1])) l--;
str[l] = '\0';
/* break loop on empty input */
if (l == 0) break;
ninput++;
}
printf("Your input:\n");
for (i = 0; i < ninput; i++) {
str = buf[i];
printf("[%d] '%s'\n", i + 1, str);
}
return 0;
}
Note the two separate loops for input and output.
I've also rejiggled your input. I'm not very fond of fscanf; I prefer to read input line-wise with fgets and then analyse the line with strtok or sscanf. The advantage over fscanf is that yout strings may contain white-space. The drawback is that you have a newline at the end which you usually don't want and have to "chomp".
If you want to allow for longer strings, you should use dynamic allocation with malloc, although I'm not sure if it is useful when reading user input from the console. Tackle that when you have understood the basics of fixed-size allocation on the stack.
Other people have already pointed you to the error in your check for uniqueness.
Is it possible to increment a number alone within a string?
So let's say I have:
char someString = "A0001";
Is there a way to increment the number '0001'? To make it A0002, A0003 etc?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char *strinc(const char *str, int d, int min_width){
char wk[12];//12:max length of sizeof(int)=4
char *p;
int len, d_len, c;
c = len = strlen(str);
while(isdigit(str[--c]));
++c;
d += strtol(&str[c], NULL, 10);
if(d<0) d = 0;
d_len = sprintf(wk, "%0*d", min_width, d);
p = malloc((c+d_len+1)*sizeof(char));
strncpy(p, str, c);
p[c]='\0';
return strcat(p, wk);
}
int main(void){
char *someString = "A0001";
char *label_x2, *label_x3;
label_x2 = strinc(someString, +1, 4);
printf("%s\n", label_x2);//A0002
label_x3 = strinc(label_x2, +1, 4);
printf("%s\n", label_x3);//A0003
free(label_x2);
label_x2 = strinc("A0008", +5, 4);
printf("%s\n", label_x2);//A0013
free(label_x3);
label_x3 = strinc(label_x2, -8, 4);
printf("%s\n", label_x3);//A0005
free(label_x2);
free(label_x3);
return 0;
}
no u cannot do it because it is a constant
The simple answer is that there is no "easy" way to do what you're asking. You would have to parse the string, extract the numerical portion and parse into a number. Increment the number and then print that number back into your string.
You could try the following simple example to base something on...
EDIT: Just read BLUEPIXY's answer... he presents a nice function that will do it for you, return you a new string, which doesn't have the width restriction of my simple answer...
There are some points worth noting...
Use char someString[] = "A0001"; and not char *someString = "A0001";. The reason is that the former allocates memory on the stack for the string, the latter is a pointer to a string in memory. The memory location decided upon by the compiler in the latter case and is not always guaranteed to be writable.
Crappy #define for snprintf on Windows... not sure that's a good thing. The point is really use a safe buffer writing function that won't overflow the bounds of your array.
The snprintf format string "%0*u" Formats an unsigned integer with a minimum width specified by the argument to the left of the actual integer and the zero tells it to left pad with zeros if necessary.
If your number increases to a width greater than, in this case, 4 digits, the buffer won't overflow, but your answers will look wrong (I haven't put in any logic to increment the buffer size)
I am assuming the the format of the string is always a set of non-numerical-digits, followed by a set of numerical digits and then a null terminator.
Now the code...
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#ifdef WIN32
#define snprintf sprintf_s
#endif
int main(int argc, char* argv[])
{
/* Assume that the string format is letters followed by numbers */
/* Note use someString[] and NOT someString* */
char someString[] = "A0001";
char *start = someString;
char *end = start + strlen(someString); /* End points to the NULL terminator */
char *endOfParse;
char c;
unsigned long num;
ptrdiff_t numDigits;
/* Find first numeric value (start will point to first numeric
* value or NULL if none found */
while( true )
{
c = *start;
if( c == '\0' || isdigit(c) )
break;
++start;
}
if( c == '\0' )
{
printf("Error: didn't find any numerical characters\n");
exit(EXIT_FAILURE);
}
/* Parse the number pointed to by "start" */
num = strtoul(start, &endOfParse, 0);
if(endOfParse < end )
{
printf("Error: Failed to parse the numerical portion of the string\n");
exit(EXIT_FAILURE);
}
/* Figure out how many digits we parsed, so that we can be sure
* not to overflow the buffer when writing in the new number */
numDigits = end - start;
num = num + 1;
snprintf(start, numDigits+1, "%0*u", numDigits, num); /* numDigits+1 for buffer size to include the null terminator */
printf("Result is %s\n", someString);
return EXIT_SUCCESS;
}
You can't do it simply because its not as simple to machine as it looks to you. There are a lot of things you need to understand about what you are trying to do first. For example, What part of string are you taking as a number which is to be incremented?
Last digit only?
A number which will be followed by SINGLE alphabet?
A number which may be followed by any number of alphabets?
LAST number in a string, for example A33B43 would mean to increment 33 or 43?
When you have answers to all such questions, you can implement them in a function. One of the many possible approaches thereafter can be to make a new substring which will represent the number to be incremented(this substring is to be taken out from your someString). Then use atoi() to convert that string into number, increment the number and replace this incremented number as a string in someString.(someString needs to be String or char * btw).