C सांत्वना कार्यक्रम में एक पूरी लाइन को पढ़ने का सबसे सरल तरीका क्या है। दर्ज किया गया पाठ एक चर लंबाई हो सकता है और हम इसकी सामग्री के बारे में कोई धारणा नहीं बना सकते।
C सांत्वना कार्यक्रम में एक पूरी लाइन को पढ़ने का सबसे सरल तरीका क्या है। दर्ज किया गया पाठ एक चर लंबाई हो सकता है और हम इसकी सामग्री के बारे में कोई धारणा नहीं बना सकते।
जवाबों:
आपको गतिशील मेमोरी प्रबंधन की आवश्यकता है, और fgets
अपनी लाइन को पढ़ने के लिए फ़ंक्शन का उपयोग करें । हालांकि, यह देखने का कोई तरीका नहीं है कि यह कितने वर्णों को पढ़ता है। तो आप fgetc का उपयोग करें:
char * getline(void) {
char * line = malloc(100), * linep = line;
size_t lenmax = 100, len = lenmax;
int c;
if(line == NULL)
return NULL;
for(;;) {
c = fgetc(stdin);
if(c == EOF)
break;
if(--len == 0) {
len = lenmax;
char * linen = realloc(linep, lenmax *= 2);
if(linen == NULL) {
free(linep);
return NULL;
}
line = linen + (line - linep);
linep = linen;
}
if((*line++ = c) == '\n')
break;
}
*line = '\0';
return linep;
}
नोट : कभी नहीं उपयोग हो जाता है! यह चेकिंग सीमा नहीं करता है और आपके बफर को ओवरफ्लो कर सकता है
fgetc_unlocked
यदि थ्रेड सुरक्षा चिंता का विषय नहीं है, लेकिन प्रदर्शन कम है तो आप कम पोर्टेबल का उपयोग कर सकते हैं ।
getline()
POSIX मानक getline()
फ़ंक्शन से अलग है ।
स्थैतिक आवंटन के लिए लाइन पढ़ने के लिए एक बहुत ही सरल लेकिन असुरक्षित कार्यान्वयन:
char line[1024];
scanf("%[^\n]", line);
बफर ओवरफ्लो की संभावना के बिना एक सुरक्षित कार्यान्वयन, लेकिन पूरी लाइन को न पढ़ने की संभावना के साथ:
char line[1024];
scanf("%1023[^\n]", line);
चर घोषित करने वाली लंबाई और प्रारूप स्ट्रिंग में निर्दिष्ट लंबाई के बीच 'अंतर से एक' नहीं। यह एक ऐतिहासिक कला है।
gets
जो मानक से पूरी तरह से हटा दिया गया था
इसलिए, यदि आप कमांड के तर्क की तलाश कर रहे थे, तो टिम के उत्तर पर एक नज़र डालें। यदि आप सिर्फ कंसोल से एक पंक्ति पढ़ना चाहते हैं:
#include <stdio.h>
int main()
{
char string [256];
printf ("Insert your full address: ");
gets (string);
printf ("Your address is: %s\n",string);
return 0;
}
हां, यह सुरक्षित नहीं है, आप बफर ओवररन कर सकते हैं, यह फाइल के अंत की जांच नहीं करता है, यह एनकोडिंग और बहुत सारे अन्य सामान का समर्थन नहीं करता है। वास्तव में मैंने यह भी नहीं सोचा कि क्या यह इस सामान में से किसी ने किया। मैं मानता हूं कि मैं थोड़े खराब हो गया हूं। ऊपर की तरह। वास्तव में, मुझे लगता है, यदि आप कोड की उन 100 पंक्तियों को वास्तविकता में लिखने की कोशिश करते हैं, तो आप कई और गलतियाँ करेंगे, जितना आपने किया होगा;
gets
कोई और अधिक मौजूद नहीं है, इस प्रकार यह C11 में काम नहीं करता है।
getline
चल उदाहरण
इस उत्तर पर उल्लेख किया गया है लेकिन यहाँ एक उदाहरण है।
यह POSIX 7 है , हमारे लिए मेमोरी आवंटित करता है, और एक लूप पर आवंटित बफर का अच्छी तरह से पुन: उपयोग करता है।
पॉइंटर न्यूब्स, इसे पढ़ें: पॉइंटर को पॉइंटर करने का पहला तर्क "चार *" के बजाय पॉइंटर "चार **" क्यों है?
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *line = NULL;
size_t len = 0;
ssize_t read = 0;
while (read != -1) {
puts("enter a line");
read = getline(&line, &len, stdin);
printf("line = %s", line);
printf("line length = %zu\n", read);
puts("");
}
free(line);
return 0;
}
glibc कार्यान्वयन
कोई POSIX? शायद तुम देखना चाहते हो glibc 2.23 कार्यान्वयन ।
इसका समाधान होता है getdelim
, जो getline
एक मनमाने ढंग से लाइन टर्मिनेटर के साथ एक सरल POSIX सुपरसेट है ।
जब भी वृद्धि की आवश्यकता होती है, यह आवंटित मेमोरी को दोगुना कर देता है, और थ्रेड-सुरक्षित दिखता है।
इसके लिए कुछ स्थूल विस्तार की आवश्यकता है, लेकिन आप बहुत बेहतर करने की संभावना नहीं रखते हैं।
len
है, जब पढ़ा जाता है तो लंबाई भी प्रदान करता है
man getline
। len
मौजूदा बफर की लंबाई है, 0
जादू है और इसे आवंटित करने के लिए कहता है। पढ़िए चार्ट की संख्या पढ़ी जाती है बफर का आकार इससे बड़ा हो सकता है read
।
मेरे जैसे कई लोग इस पद पर आते हैं, जो कि खोजे जाने वाले शीर्षक से मेल खाते हैं, हालांकि वर्णन चर लंबाई के बारे में कह रहा है। अधिकांश मामलों के लिए, हम पहले से लंबाई जानते हैं।
यदि आप हाथ से पहले लंबाई जानते हैं, तो नीचे देखें:
char str1[1001] = { 0 };
fgets(str1, 1001, stdin); // 1000 chars may be read
स्रोत: https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm
जैसा कि सुझाव दिया गया है, आप कंसोल से पढ़ने के लिए गेटचेयर () का उपयोग कर सकते हैं जब तक कि एक अंत-पंक्ति या ईओएफ वापस नहीं किया जाता है, अपने स्वयं के बफर का निर्माण। यदि आप एक उचित अधिकतम लाइन आकार सेट करने में असमर्थ हैं, तो गतिशील रूप से बफर बढ़ सकता है।
आप सी-नल-समाप्त स्ट्रिंग के रूप में एक लाइन प्राप्त करने के लिए एक सुरक्षित तरीके के रूप में भी उपयोग कर सकते हैं:
#include <stdio.h>
char line[1024]; /* Generously large value for most situations */
char *eof;
line[0] = '\0'; /* Ensure empty line if no input delivered */
line[sizeof(line)-1] = ~'\0'; /* Ensure no false-null at end of buffer */
eof = fgets(line, sizeof(line), stdin);
यदि आपने कंसोल इनपुट समाप्त कर दिया है या किसी कारणवश ऑपरेशन विफल हो गया है, तो eof == NULL वापस आ गया है और लाइन बफर अपरिवर्तित हो सकता है (यही वजह है कि पहला char को '\ 0' में सेट करना आसान है)।
फ़िज़ूल लाइन खत्म नहीं होगी [और यह सुनिश्चित करेगा कि एक सफल वापसी पर अंतिम-स्वीकृत चरित्र के बाद एक अशक्त हो।
यदि एंड-ऑफ-लाइन पहुंच गया था, तो '\ 0' को समाप्त करने से पहले का वर्ण '\ n' होगा।
यदि '' 0 'को समाप्त करने से पहले कोई समाप्ति' \ n 'नहीं है तो हो सकता है कि अधिक डेटा हो या कि अगला अनुरोध एंड-ऑफ़-फ़ाइल की रिपोर्ट करेगा। आपको यह निर्धारित करने के लिए एक और बजट करना होगा कि कौन सा है। (इस संबंध में, गेटचेयर के साथ लूपिंग आसान है।)
ऊपर (अद्यतित) उदाहरण कोड में, यदि लाइन [sizeof (लाइन) -1] == '0' सफल होने के बाद, आप जानते हैं कि बफर पूरी तरह से भरा हुआ था। यदि वह स्थिति '\ n' द्वारा आगे बढ़ाई जाती है, तो आप जानते हैं कि आप भाग्यशाली थे। अन्यथा, स्टैड में आगे या तो अधिक डेटा या एक एंड-ऑफ-फ़ाइल है। (जब बफर पूरी तरह से भरा नहीं है, तो आप अभी भी एक फ़ाइल के अंत में हो सकते हैं और वर्तमान लाइन के अंत में एक '\ n' भी नहीं हो सकता है। चूंकि आपको खोजने और / के लिए स्ट्रिंग को स्कैन करना होगा। या स्ट्रिंग के अंत से पहले किसी भी '\ n' को समाप्त करें (बफर में पहला '\ 0'), मैं पहली जगह में getchar () का उपयोग करना पसंद कर रहा हूँ।)
पहले चंक के रूप में पढ़ी गई राशि से अधिक लाइन होने के बावजूद आपको जो करने की आवश्यकता है, वह करें। गतिशील रूप से बढ़ते हुए बफर के उदाहरणों को गेटचार या फ़्यूज़ के साथ काम करने के लिए बनाया जा सकता है। बाहर देखने के लिए कुछ ट्रिकी एज केस हैं (जैसे कि याद है कि अगला इनपुट शुरू होने की स्थिति में '\ 0' की स्थिति में बफर इनपुट से पहले पिछले इनपुट को समाप्त कर दिया था)।
C में कंसोल से एक लाइन कैसे पढ़ें?
अपने स्वयं के फ़ंक्शन का निर्माण करना, उन तरीकों में से एक है जो आपको कंसोल से एक लाइन पढ़ने में मदद करेगा
मैं आवश्यक स्मृति की आवश्यक मात्रा आवंटित करने के लिए गतिशील मेमोरी आवंटन का उपयोग कर रहा हूं
जब हम आवंटित मेमोरी को समाप्त करने वाले होते हैं, तो हम मेमोरी के आकार को दोगुना करने की कोशिश करते हैं
और यहां मैं एक लूप का उपयोग कर रहा हूं ताकि स्ट्रिंग के प्रत्येक चरित्र को एक-एक करके getchar()
फ़ंक्शन का उपयोग किया जा सके जब तक कि उपयोगकर्ता प्रवेश '\n'
या EOF
चरित्र नहीं करता
अंत में हम लाइन को वापस करने से पहले किसी भी अतिरिक्त रूप से आवंटित मेमोरी को हटा देते हैं
//the function to read lines of variable length
char* scan_line(char *line)
{
int ch; // as getchar() returns `int`
long capacity = 0; // capacity of the buffer
long length = 0; // maintains the length of the string
char *temp = NULL; // use additional pointer to perform allocations in order to avoid memory leaks
while ( ((ch = getchar()) != '\n') && (ch != EOF) )
{
if((length + 1) >= capacity)
{
// resetting capacity
if (capacity == 0)
capacity = 2; // some initial fixed length
else
capacity *= 2; // double the size
// try reallocating the memory
if( (temp = realloc(line, capacity * sizeof(char))) == NULL ) //allocating memory
{
printf("ERROR: unsuccessful allocation");
// return line; or you can exit
exit(1);
}
line = temp;
}
line[length] = (char) ch; //type casting `int` to `char`
}
line[length + 1] = '\0'; //inserting null character at the end
// remove additionally allocated memory
if( (temp = realloc(line, (length + 1) * sizeof(char))) == NULL )
{
printf("ERROR: unsuccessful allocation");
// return line; or you can exit
exit(1);
}
line = temp;
return line;
}
अब आप इस तरह से एक पूरी लाइन पढ़ सकते हैं:
char *line = NULL;
line = scan_line(line);
यहाँ एक उदाहरण कार्यक्रम का उपयोग कर कार्यक्रम हैscan_line()
:
#include <stdio.h>
#include <stdlib.h> //for dynamic allocation functions
char* scan_line(char *line)
{
..........
}
int main(void)
{
char *a = NULL;
a = scan_line(a); //function call to scan the line
printf("%s\n",a); //printing the scanned line
free(a); //don't forget to free the malloc'd pointer
}
नमूना इनपुट:
Twinkle Twinkle little star.... in the sky!
नमूना उत्पादन:
Twinkle Twinkle little star.... in the sky!
मैं कुछ समय पहले इसी समस्या में आया था, यह मेरा विलेयशन था, आशा है कि यह मदद करेगा।
/*
* Initial size of the read buffer
*/
#define DEFAULT_BUFFER 1024
/*
* Standard boolean type definition
*/
typedef enum{ false = 0, true = 1 }bool;
/*
* Flags errors in pointer returning functions
*/
bool has_err = false;
/*
* Reads the next line of text from file and returns it.
* The line must be free()d afterwards.
*
* This function will segfault on binary data.
*/
char *readLine(FILE *file){
char *buffer = NULL;
char *tmp_buf = NULL;
bool line_read = false;
int iteration = 0;
int offset = 0;
if(file == NULL){
fprintf(stderr, "readLine: NULL file pointer passed!\n");
has_err = true;
return NULL;
}
while(!line_read){
if((tmp_buf = malloc(DEFAULT_BUFFER)) == NULL){
fprintf(stderr, "readLine: Unable to allocate temporary buffer!\n");
if(buffer != NULL)
free(buffer);
has_err = true;
return NULL;
}
if(fgets(tmp_buf, DEFAULT_BUFFER, file) == NULL){
free(tmp_buf);
break;
}
if(tmp_buf[strlen(tmp_buf) - 1] == '\n') /* we have an end of line */
line_read = true;
offset = DEFAULT_BUFFER * (iteration + 1);
if((buffer = realloc(buffer, offset)) == NULL){
fprintf(stderr, "readLine: Unable to reallocate buffer!\n");
free(tmp_buf);
has_err = true;
return NULL;
}
offset = DEFAULT_BUFFER * iteration - iteration;
if(memcpy(buffer + offset, tmp_buf, DEFAULT_BUFFER) == NULL){
fprintf(stderr, "readLine: Cannot copy to buffer\n");
free(tmp_buf);
if(buffer != NULL)
free(buffer);
has_err = true;
return NULL;
}
free(tmp_buf);
iteration++;
}
return buffer;
}
goto
त्रुटि मामले को संभालने के लिए उपयोग करते हैं तो आपका कोड बहुत सरल हो जाएगा । फिर भी, आपको नहीं लगता कि आप पुन: उपयोग कर सकता है tmp_buf
, बजाय malloc
पाश में पर एक ही आकार के साथ यह ing?
has_err
त्रुटियों की रिपोर्ट करने के लिए एक एकल वैश्विक चर का उपयोग इस फ़ंक्शन को थ्रेड-असुरक्षित और उपयोग करने के लिए आरामदायक से कम बनाता है। इस तरह मत करो। NULL को वापस करके आप पहले से ही एक त्रुटि दर्शाते हैं। यह सोचने के लिए भी जगह है कि मुद्रित त्रुटि संदेश एक सामान्य-उद्देश्य लाइब्रेरी फ़ंक्शन में एक अच्छा विचार नहीं है।
बीएसडी सिस्टम और एंड्रॉइड पर भी आप उपयोग कर सकते हैं fgetln
:
#include <stdio.h>
char *
fgetln(FILE *stream, size_t *len);
इस तरह:
size_t line_len;
const char *line = fgetln(stdin, &line_len);
line
अशक्त समाप्त नहीं है और होता है \n
अंत में (या जो भी अपने मंच का उपयोग कर रहा है)। स्ट्रीम पर अगले I / O ऑपरेशन के बाद यह अमान्य हो जाता है।
कुछ इस तरह:
unsigned int getConsoleInput(char **pStrBfr) //pass in pointer to char pointer, returns size of buffer
{
char * strbfr;
int c;
unsigned int i;
i = 0;
strbfr = (char*)malloc(sizeof(char));
if(strbfr==NULL) goto error;
while( (c = getchar()) != '\n' && c != EOF )
{
strbfr[i] = (char)c;
i++;
strbfr = (void*)realloc((void*)strbfr,sizeof(char)*(i+1));
//on realloc error, NULL is returned but original buffer is unchanged
//NOTE: the buffer WILL NOT be NULL terminated since last
//chracter came from console
if(strbfr==NULL) goto error;
}
strbfr[i] = '\0';
*pStrBfr = strbfr; //successfully returns pointer to NULL terminated buffer
return i + 1;
error:
*pStrBfr = strbfr;
return i + 1;
}
कंसोल से एक पंक्ति को पढ़ने का सबसे अच्छा और सरल तरीका गेटचार () फ़ंक्शन का उपयोग कर रहा है, जिसके तहत आप एक सरणी में एक बार में एक चरित्र को संग्रहीत करेंगे।
{
char message[N]; /* character array for the message, you can always change the character length */
int i = 0; /* loop counter */
printf( "Enter a message: " );
message[i] = getchar(); /* get the first character */
while( message[i] != '\n' ){
message[++i] = getchar(); /* gets the next character */
}
printf( "Entered message is:" );
for( i = 0; i < N; i++ )
printf( "%c", message[i] );
return ( 0 );
}
इस समारोह में वह करना चाहिए जो आप चाहते हैं:
char* readLine( FILE* file )
{
char buffer[1024];
char* result = 0;
int length = 0;
while( !feof(file) )
{
fgets( buffer, sizeof(buffer), file );
int len = strlen(buffer);
buffer[len] = 0;
length += len;
char* tmp = (char*)malloc(length+1);
tmp[0] = 0;
if( result )
{
strcpy( tmp, result );
free( result );
result = tmp;
}
strcat( result, buffer );
if( strstr( buffer, "\n" ) break;
}
return result;
}
char* line = readLine( stdin );
/* Use it */
free( line );
आशा है कि ये आपकी मदद करेगा।
fgets( buffer, sizeof(buffer), file );
नहीं करना चाहिए sizeof(buffer)-1
। fgets
समाप्ति नल के लिए जगह छोड़ देता है।
while (!feof(file))
यह हमेशा गलत है और यह गलत उपयोग का सिर्फ एक और उदाहरण है।