arrays from txt in c (long numbers) - c

400000000000;499999999999;VISA;
50000000;59999999;MASTERCARD;
67000000;67999999;MAESTRO;
fields: 1. Range Start 2. Range End, 3 Name.
[Start Range] and [End Range] fields can be from 1 to 16 characters (digits) in length.
The program's objective is as follows:
First Request to enter 16-digit card number.
Card number input, verification and processing use char [n] type (Simbol array)
Second:Check for an entry corresponding to the entered card number can be found in a text file if I enter 45000000000 it's between 400000000000 and 499999999999 so i need to put a text in a autput name VISA.
And i can't use long long types... as i undrstand i need to use arrays...
Third Request to enter the amount in the format "nnnn.mm", where nnnn-1 to 4 digits long amount of lats, but mm - 2-digit amount santims.
char input[32]; // = "100;200;first";
char name[10];
int min, max, c, i, k;
FILE *file;
file = fopen("gg.txt","r");
i=0;
while ((c=getc(file))!= EOF)
{
k=(int)c;
input[i]=k;
i++;
}
char* result = NULL;
char delims[] = ";";
result = strtok(input, delims);
// atoi() converts ascii to integer.
min = atoi(result);
result = strtok(NULL, delims);
max = atoi(result);
result = strtok(NULL, delims);
strcpy(name, result);
printf("Min=%d, Max=%d, Name=%s\n", min, max, name);
printf("input=%s\n",input);
printf("%d\n",i);
getch();
return 0;
this code given me by varunl works vith smal numbers ( the containing of gg.txt file is: 100;200;first), but a need smt else, enybody, can help me?

The trick is in padding the numbers to 16 digits, so you can compare them as strings. So if you read this:
67000000;67999999;MAESTRO;
in reality you have to consider it like this:
0000000067000000;0000000067999999;MAESTRO;
The same for the user input.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void FindCCType(const char *pnumber);
int main(int argc, char *argv[])
{
FindCCType("67000001");
return 0;
}
#define MAXLENGTH 16
char* PadLeft(const char *pnumber)
{
char *pnumber2 = (char*)malloc(MAXLENGTH + 1);
size_t len = strlen(pnumber);
if (len > MAXLENGTH)
{
/* Too many digits in credit card number */
exit(1);
}
strcpy(pnumber2 + MAXLENGTH - len, pnumber);
char *pbegin = pnumber2, *plast = pnumber2 + MAXLENGTH - len;
while (pbegin < plast)
{
*pbegin = '0';
pbegin++;
}
return pnumber2;
}
void FindCCType(const char *pnumber)
{
printf("Input: %s\n", pnumber);
char *pnumber2 = PadLeft(pnumber);
FILE *file = fopen("gg.txt","r");
char pline[1000];
while (fgets(pline, sizeof(pline), file) != NULL)
{
if (strlen(pline) + 1 == sizeof(pline))
{
/* Line too much long */
exit(2);
}
char *pmin = strtok(pline, ";");
char *pmax = strtok(NULL, ";");
char *pname = strtok(NULL, ";");
printf("Min: %s, Max: %s, Name: %s", pmin, pmax, pname);
char *pmin2 = PadLeft(pmin);
char *pmax2 = PadLeft(pmax);
if (strcmp(pnumber2, pmin2) >= 0 && strcmp(pnumber2, pmax2) <= 0)
{
printf(" ** FOUND **\n");
free(pmin2);
free(pmax2);
break;
}
printf(" ** NO GOOD **\n");
free(pmin2);
free(pmax2);
}
fclose(file);
free(pnumber2);
}

Related

Splitting a string from a input without using strtok()

I have been working on a program to read zip codes and populations from a .csv file and find the zip code with the largest and smallest population. I'm tasked to do this without using scanf(all variants) and strtok(). Currently, it outputs the entire string and I do not know how to split the string into just zip code and population. Any help is appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int lines = 1024; //Maximum lines, specified
char str[256]; //Maximum characters, specified
char* pEnd = str;
//Variables for parsing data
char zipCode[256];
char population[256];
long bufPopulation = 0; //Variable to convert from string to long
//Variables to track the number of zipcodes and total population
static int NumOfZipCodes = 0;
static long totalPopulation = 0;
for (int i = 0; i < lines && fgets(str, sizeof(str), stdin); i++){
//parses the data being read into variable 'str'
strcpy(zipCode, str);
strcpy(population, str);
printf("String %s", str); //outputs str
printf("Zip codes %s", zipCode); //outputs zipCode
printf("Population %s", population); //outputs population
if (i > 0){
bufPopulation = strtol(population, &pEnd, 10);
printf("Buffer population %.0ld", bufPopulation); //outputs the long value of population
totalPopulation += bufPopulation;
NumOfZipCodes++;
}
}
int size = sizeof population/sizeof population[0];
long maxPop, minPop = 0;
char maxZip, minZip = zipCode[0];
for (int i = 1; i < size; i++){
bufPopulation = strtol(population, &pEnd, 10);
if (minPop > bufPopulation)
{
minPop = bufPopulation;
minZip = zipCode[i];
}
if (maxPop < bufPopulation)
{
maxPop = bufPopulation;
maxZip = zipCode[i];
}
}
//Displays the stored values
printf("Total Population across %d zipcodes is ", NumOfZipCodes);
printf("%.0ld\n", totalPopulation);
printf("The fewest people live in %.0d, population ", minZip);
printf("%.0ld\n", minPop);
printf("The most people live in %.0d, population ", maxZip);
printf("%.0ld\n", maxPop);
return 0;
}
The strtol() function assigns endptr, which is pointed by the second
argument, to the address of the remaining string after converting the valid
substring into the long integer. The character pointed by the address will
be normally the delimiter or the newline character at the end of the string.
Then you can repeat calling strtod() and skipping the delimiter to parse
the columns of the csv line. Would you please try the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCHARS 256 // max characters in a line
#define DELIM ' ' // column delimiter
int main() {
char str[MAXCHARS]; // line buffer
char *eptr; // pointer within str
int zip, minZip, maxZip;
long pop, minPop, maxPop;
int numOfZipCodes = 0;
long totalPopulation = 0;
fgets(str, MAXCHARS, stdin); // read the header and discard
while (fgets(str, MAXCHARS, stdin)) { // read each line
zip = (int)strtol(str, &eptr, 10); // parse the zip code
if (*eptr != DELIM) { // check the next delimiter
fprintf(stderr, "illegal input string: %s", str);
exit(1);
}
while (*eptr == DELIM) eptr++; // skip the delimiter
pop = strtol(eptr, &eptr, 10); // parse the population
if (*eptr != DELIM) { // check the next delimiter
fprintf(stderr, "illegal input string: %s", str);
exit(1);
}
printf("Zip code %d\n", zip); // output zip code
printf("Population %ld\n", pop); // output population
if (numOfZipCodes == 0) { // initialize values on the 1st line
minPop = maxPop = pop;
minZip = maxZip = zip;
} else {
if (minPop > pop) {
minPop = pop;
minZip = zip;
}
if (maxPop < pop) {
maxPop = pop;
maxZip = zip;
}
}
totalPopulation += pop;
numOfZipCodes++;
}
// display the results
printf("Total Population across %d zipcodes is %ld\n", numOfZipCodes, totalPopulation);
printf("The fewest people live in %d, population %ld\n", minZip, minPop);
printf("The most people live in %d, population %ld\n", maxZip, maxPop);
return 0;
}
It assumes the delimiter is a whitespace as shown in your comment. If the
deimiter is a comma or other character, modify the #define DELIM ' ' line
accordingly.

Store splitted string in array

I using strtok() to split a string and store in an array like following below
char *table[5];
char buffer[50] = {"1-Study"}; // The value is example, get new value by user
char *number;
char *name;
uint8_t tableNumber;
number = strtok(buffer, "-"); //equals "1"
name = strtok(NULL, "-"); //equals "Study"
tableNumber = atoi(number); //convert char to int
table[tableNumber] = name;
for (c = 0; c < 5; c++)
{
printf("table %d = %s\n", c, table[c]);
}
after get input for 5 times the result should be:
table 0 = Study
table 1 = Sleep
table 2 = Party
table 3 = Hello
table 4 = Exit
But the resualt is:
table 0 = Exit
table 1 = Exit
table 2 = Exit
table 3 = Exit
table 4 = Exit
whats the problem?
please help me?
Thanks
complete code:
char gMessageBuffer[40];
char *gSceneTable[13];
boolean emberAfPreMessageReceivedCallback(EmberAfIncomingMessage* incomingMessage)
{
if (incomingMessage->apsFrame->profileId == HA_PROFILE_ID)
{
if (incomingMessage->apsFrame->clusterId == ZCL_SCENES_CLUSTER_ID)
{
MEMCOPY(gMessageBuffer, incomingMessage->message, incomingMessage->msgLen); // Get incoming message
gMessageBuffer[incomingMessage->msgLen] = '\0';
emberEventControlSetDelayMS(getScenePayloadEventControl, SCENE_ACTION_TRESH);
return true;
}
}
return false;
}
void getScenePayloadEventFunction(void)
{
char *sceneNumber;
char *sceneName;
char *sceneID;
char *sceneAction;
uint8_t sceneTableNumber;
emberAfCorePrintln("///Incoming Message: %s///", gMessageBuffer);
sceneNumber = strtok(gMessageBuffer, ".");
sceneName = strtok(NULL, ".");
sceneID = strtok(NULL, ".");
sceneAction = strtok(NULL, ".");
emberAfCorePrintln("///SCENE NUMBER: %s///", sceneNumber);
emberAfCorePrintln("///SCENE NAME: %s///", sceneName);
emberAfCorePrintln("///SCENE ID: %s///", sceneID);
emberAfCorePrintln("///SCENE ACTION: %s///", sceneAction);
if (strcmp(sceneAction, "Update") == 0)
{
sceneTableNumber = atoi(sceneNumber);
gSceneTable[sceneTableNumber] = strdup(sceneName);
}
emberEventControlSetInactive(getScenePayloadEventControl);
}
this is for microcontroller in simplicity studio IDE.
I get payload in emberAfPreMessageReceivedCallback correctly
and I split it into 4 parts and print correctly too.
But after copy the sceneName to gSceneTable array I see the last sceneName in all the elements of gSceneTable with gSceneTable[sceneTableNumber] = sceneName and I see "p]" with gSceneTable[sceneTableNumber] = strdup(sceneName);
It is highly unlikely that your program produce the posted output. The code fragment only handles a single string and char *table[5]; is uninitialized, so printing the strings from table[0], table[2], table[3] and table[4] has undefined behavior. You specified that the strings are read from a file, posting a complete program is required for a precise and correct analysis. Not initializing the array is a problem in case the file does not have all entries covered, it would be impossible to tell which were set and which weren't.
Assuming your program reads the strings from a file or standard input, parsing them with strtok returns pointers to the source string, which is the array into which you read the lines from the file. Hence all entries in the table[] array point to the same byte in this array, which explains the output you get: 5 times the contents of the last line.
You should make a copy of the string you store in the table:
table[tableNumber] = strdup(name);
Here is a completed and modified program:
#include <stdio.h>
#include <string.h>
int main() {
char *table[5] = { NULL, NULL, NULL, NULL, NULL };
char buffer[50];
char *number;
char *name;
int tableNumber;
for (int i = 0; i < 5; i++) {
if (!fgets(buffer, sizeof buffer, stdin))
break;
number = strtok(buffer, "-");
if (number == NULL) {
printf("empty line\n");
continue;
}
name = strtok(NULL, "-\n");
if (name == NULL) {
printf("no name after -\n");
continue;
}
tableNumber = atoi(number);
if (tableNumber < 0 || tableNumber >= 5) {
printf("invalid number: %d\n", tableNumber);
continue;
}
table[tableNumber] = strdup(name);
}
for (int i = 0; i < 5; i++) {
if (table[i])
printf("table %d = %s\n", i, table[i]);
}
for (int i = 0; i < 5; i++) {
free(table[i]);
}
return 0;
}
If your target system does not support strdup(), use this:
#include <stdlib.h>
#include <string.h>
char *mystrdup(const char *s) {
size_t size = strlen(s) + 1;
char *p = malloc(size);
return (p != NULL) ? memcpy(p, s, size) : NULL;
}
The sample code:
Enter message like "sceneNumber.sceneName.sceneID.Update"
For example: 1.Study.12345.Update
#include <stdio.h>
#include <string.h>
#include <conio.h>
char *gSceneTable[13];
char gMessageBuffer[50];
int main()
{
char *sceneNumber;
char *sceneName;
char *sceneID;
char *sceneAction;
int sceneTableNumber;
int check;
int c;
printf("Enter payload for 3 Times\r\n");
while(check != 3)
{
scanf("%s", &gMessageBuffer);
printf("Message is: %s\r\n",gMessageBuffer);
sceneNumber = strtok(gMessageBuffer, ".");
sceneName = strtok(NULL, ".");
sceneID = strtok(NULL, ".");
sceneAction = strtok(NULL, ".");
printf("%s\r\n", sceneNumber);
printf("%s\r\n", sceneName);
printf("%s\r\n", sceneID);
printf("%s\r\n", sceneAction);
if (strcmp(sceneAction, "Update") == 0)
{
sceneTableNumber = atoi(sceneNumber);
gSceneTable[sceneTableNumber] = sceneName;
}
check++;
}
for (c = 0; c < 4; c++)
{
printf("Scene Table: %d ----- %s \r\n", c, gSceneTable[c]);
}
return 0;
}

How to shift letters to the right or left?

I am given a file with a string, for example "The United States was founded in *1776*". What I cannot figure out is how to shift letters one space to the left or right and have the letters wrap around. I am able to shift the letters from an a to b but not change its location within the word.
Example of this output would be:
"heT
nitedU
tatesS
asw
oundedf
ni
1776**"
In C, strings are stored as an array of chars in memory. Unlike C++ vectors, you can not insert or remove element within the array, you can only access their value or change their value.
If you declare a C string as follows:
char *myStr = "Fred";
It will be stored in memory as a five character array with the 5th character being the zero value which terminates a C string:
myStr[0] = 'F'
myStr[1] = 'r'
myStr[2] = 'e'
myStr[3] = 'd'
myStr[4] = 0
You need to design a for loop that copies each array element to the one before, while remembering that you need to save the one you are about to overwrite. In this example, it should result in the following copy operations being performed:
len = strlen(myStr);
saveCh = myStr[0];
myStr[0] = myStr[1];
myStr[1] = myStr[2];
myStr[2] = myStr[3];
myStr[3] = saveCh;
So now your job is to create a for loop that does that for any C string of any length.
So to rotate the chars within a C string to the left, you need to copy each char in the array at index i to previous array element i-1. The tricky part is to handle the wrap around properly when i=0 (in this example, you want to copy myStr[0] to myStr[3]. Now do that with a for loop.
You need to also understand that the last character of any C string is the null character (value zero), which terminates a C string. If you modify that element in the array, then your string will break. That is why saveCh is copied to myStr[3] and not to myStr[4].
void rotateStrLeftOneChar(char *myStr) {
// Always check for error and special cases first!
// If myStr is a NULL pointer, do nothing and exit
// If myStr is less than 2 chars, nothing needs to be done too.
if ((myStr != NULL) && (strlen(myStr)>1)) {
int len = strlen(myStr);
char saveCh = myStr[0];
int i = 0;
// Copy each char at index i+1 left to index i in the array
for(i=0; i<len-2; i++)
myStr[i] = myStr[i+1];
// The last character is special and is set to saveCh
myStr[len-1] = saveCh;
}
}
If you just need to output the letters to shift to the left and don't want to change original input then you can do:
#include <stdio.h>
#include <string.h>
void shiftletters(char * input, int i);
int main () {
char input[256];
int shift;
printf("Enter input : ");
scanf("%[^\n]s", input);
printf("Number of shifts : ");
scanf("%d", &shift);
shiftletters(input, shift);
return 0;
}
void shiftletters(char * input, int numshifts)
{
char str[256] = {'\0'};
char * delim = " \t";
char * pch = NULL;
int j, k, len, shifts;
if (input == NULL)
{
printf ("Invalid input\n");
return;
}
strcpy (str, input);
pch = strtok (str, delim);
while (pch != NULL)
{
len = strlen (pch);
if ((numshifts == len) || (len == 1))
{
printf ("%s\n", pch);
pch = strtok (NULL, delim);
continue;
}
if (len < numshifts)
shifts = numshifts % len;
else
shifts = numshifts;
for(j=shifts; j<len; j++)
printf("%c", pch[j]);
for(k=0; k<shifts; k++)
printf("%c", pch[k]);
printf("\n");
pch = strtok (NULL, delim);
}
}
The output of the program:
Enter input : The United States was founded in *1776*
Number of shifts : 1
heT
nitedU
tatesS
asw
oundedf
ni
1776**
like this
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
enum { L = -1, R = 1};
char *rotate(char word[], int dir){
size_t len = strlen(word);
char *temp = malloc(len + 1);
if(!temp){
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(temp, word);
for(char *src = temp; *src; ++src, ++dir){//or use memmove
word[(dir+len)%len] = *src;
}
free(temp);
return word;
}
int main(int argc, char *argv[]) {
FILE *fp = fopen("data.txt", "r");
if(fp == NULL){
perror("fopen");
exit(EXIT_FAILURE);
}
if(argc < 2){
fprintf(stderr, "Usage %s L|R...\n", argv[0]);
exit(EXIT_FAILURE);
}
char word[64];
while(fscanf(fp, "%63s", word)==1){
for(char *shift = argv[1]; *shift; ++shift){
int dir = *shift == 'L' ? L : R;
rotate(word, dir);
}
printf("%s\n", word);
}
fclose(fp);
}
using memmove version
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
enum { L = -1, R = 1};
char *rotate1(char word[], int dir){
size_t len = strlen(word);
if(len > 2){
char temp;
if(dir == L){
temp = word[0];
memmove(word, word+1, len-1);
word[len-1] = temp;
} else if(dir == R){
temp = word[len-1];
memmove(word+1, word, len-1);
word[0] = temp;
}
}
return word;
}
int main(int argc, char *argv[]) {
FILE *fp = fopen("data.txt", "r");
if(fp == NULL){
perror("fopen");
exit(EXIT_FAILURE);
}
if(argc < 2){
fprintf(stderr, "Usage %s L|R...\n", argv[0]);
exit(EXIT_FAILURE);
}
char word[64];
while(fscanf(fp, "%63s", word)==1){
for(char *shift = argv[1]; *shift; ++shift){
int dir = *shift == 'L' ? L : R;
rotate1(word, dir);
}
printf("%s\n", word);
}
}

Find Nth Word given a file of Strings and ints C

I need to find the Nth word in a string which is given through standard input through redirection operators in Unix.
Input is something along these lines:
But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born
5
The European languages are members of the same family.
3
Can anyone give me any idea as to how to read in the string into a char array and then get the int and use it to find the given word? I've been at it for a while and can't get it to work properly.
#define INPUT_LENGTH 400
int main(void)
{
char input[INPUT_LENGTH];
char integer[INPUT_LENGTH];
int spaces = 0;
int value;
char n;
while(fgets(input, INPUT_LENGTH, stdin)) //read in string line
{
while(fgets(integer, INPUT_LENGTH,stdin)) //read in int
{
int num = sscanf(integer, "%d", &value); //assign int val to num
while(1 == sscanf(input, "%c", &n)) //go through string one char at a time
if(spaces == num && !isspace(n))
printf("%c", n); //print chars if we've reached the word
else if(isspace(n))
spaces++;
}
}
}
I've redone most of it with the comments in mind but still can't seem to have it actually reading in the input through the operator unfortunately.
I'm not certain but I don't think my fgets are correct. I'm rather new to C and am not entirely certain how they process the data even after research
Use strtok like this
#include <stdio.h>
#include <string.h>
#define INPUT_LENGTH 400
int main(void){
char input[INPUT_LENGTH];
char integer[INPUT_LENGTH];
int value;
while(fgets(input, sizeof input, stdin)) //read in string line
{
if(fgets(integer, sizeof integer, stdin)) //read in int
{
if(1==sscanf(integer, "%d", &value)) //assign int value to value
{
char *word = strtok(input, " \t\n");
int n;
for(n = 1; word != NULL && n < value; ++n){// 1 origin
word = strtok(NULL, " \t\n");
}
if(word != NULL && n == value)
puts(word);//Nth word
else
puts("No word");
}
else {
printf("Numerical value is not specified.\n");
}
}
else {
printf("There is no numeric specification line.\n");
}
}
}

How to scan a string for specific terms

I'm trying to scan user input text for specific words and then, when those words occur, print them to the console.
#import <Foundation/Foundation.h>
#include <stdio.h>
int main(){
char cArray[] = "example";
char cInput[] = "";
char cOutput[] = "";
printf("\nType your message:\n");
for (int y=0; y<1; y++){
fgets(cInput, 120, stdin);
}
printf("\nInitialised character array:\n");
for (int x=0; x<1; x++){
if(strncmp(&cInput[x], &cArray[x], 120) == 0){
strncpy(cOutput, cArray, strnlen(cInput, +1));
printf("%s\n", cOutput);
break;
}
}
}
Output:
Type your message:
example
Initialised character array:
Program ended with exit code: 120
Appreciate any feedback as I'm still learning :)
Thanks.
The edited code:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main(){
char *cArray[MAX_STR_LEN] = {"example", "this"};
char cInput[MAX_STR_LEN] = "";
char cOutput[MAX_STR_LEN] = "";
printf("Type your message:\n");
for (int y=0; y<1; y++){
fgets(cInput, MAX_STR_LEN, stdin);
char * ptr = cInput;
while((ptr=strstr(ptr, *cArray)) != NULL){
strncpy(cOutput, ptr, strlen(*cArray));
printf("Initialised string array:\n%s\n", cOutput);
ptr++;
}
}
}
Works although I'm encountering a different problem now. The output only seems to register one word before it completes, thus only "example" is printed.
Output:
Type your message:
this is an example
Initialised string array:
example
Program ended with exit code: 0
char cInput[] = "";
The sizeof this array is 1.
fgets(cInput, 120, stdin);
This is array out of bound write which will lead to undefined behavior.
Have
char cInput[120] = "";
You need to take care of
char cOutput[120] = "";
also. Since you are trying to write to this array after comparing.
You need strstr function from string.h
const char * strstr ( const char * str1, const char * str2 );
the following gives you an example of usage:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main(){
char cArray[MAX_STR_LEN] = "example"; // string to be searched in the input string
char cInput[MAX_STR_LEN] = ""; // input string
char cOutput[MAX_STR_LEN] = ""; // buffer for found string
printf("\nType your message:\n");
for (int y=0; y<1; y++){ // this loop from original example looks strange, but it works
fgets(cInput, MAX_STR_LEN, stdin);
}
// search in the input string
char * ptr;
if( ( ptr=strstr(cInput, cArray) ) != NULL)
{
//copy the string to cOutput
strncpy(cOutput, ptr, strlen(cArray));
// output the found string
printf("String that was found: \n%s\n", cOutput);
}
else
{
printf("String was not found in the input!\n");
}
}
EDIT:
If you want to all the strings, use the following loop instead of if-else:
// search in the input string
char * ptr = cInput;
while( ( ptr=strstr(ptr, cArray) ) != NULL)
{
//copy the string to cOutput
strncpy(cOutput, ptr, strlen(cArray));
// output the found string
printf("String \"%s\" was found at position %d\n", cOutput, (int)(ptr - cInput + 1));
// find next string
ptr++;
}

Resources