উত্তর:
আপনার ডায়নামিক মেমরি পরিচালনা দরকার এবং 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()
এটি পসিক্স স্ট্যান্ডার্ড getline()
ফাংশন থেকে পৃথক ।
স্থির বরাদ্দের জন্য লাইন পড়ার জন্য একটি খুব সাধারণ তবে অনিরাপদ বাস্তবায়ন:
char line[1024];
scanf("%[^\n]", line);
বাফার ওভারফ্লো হওয়ার সম্ভাবনা ছাড়াই একটি নিরাপদ বাস্তবায়ন, তবে পুরো লাইনটি না পড়ার সম্ভাবনা সহ, হ'ল:
char line[1024];
scanf("%1023[^\n]", line);
ভেরিয়েবল ঘোষণা করে নির্দিষ্ট দৈর্ঘ্যের এবং বিন্যাসের স্ট্রিংয়ে উল্লিখিত দৈর্ঘ্যের মধ্যে 'একের ব্যবধানে' নয়। এটি একটি historicalতিহাসিক নিদর্শন।
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 টি কোডের কোড নয় উপরের মত আসলে, আমি মনে করি, আপনি যদি এই 100 টি কোড লাইনের বাস্তবে লেখার চেষ্টা করেন তবে আপনি যা করেছেন তা বেছে নেওয়ার চেয়ে আপনি আরও অনেক ভুল করতে পারবেন;)
gets
আর বিদ্যমান নেই, সুতরাং এটি সি 11 এ কাজ করে না।
getline
চলমান উদাহরণ
এই উত্তরে উল্লিখিত তবে এখানে একটি উদাহরণ রয়েছে।
এটি পজিক্স is , আমাদের জন্য মেমরি বরাদ্দ করে এবং একটি লুপে বরাদ্দ করা বাফারটিকে সুন্দরভাবে পুনরায় ব্যবহার করে।
পয়েন্টার newbs, এটি পড়ুন: কেন getline প্রথম পয়েন্টার পয়েন্টার পয়েন্টার "চর **" পরিবর্তে "চর *"?
#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 বাস্তবায়ন
পসিক্স নেই? হতে পারে আপনি glibc 2.23 বাস্তবায়নটি দেখতে চান ।
এটি সমাধান করে getdelim
, যা getline
একটি স্বেচ্ছাসেবী লাইন টার্মিনেটর সহ একটি সাধারণ পসিক্স সুপারস্টেট ।
এটি যখনই বৃদ্ধি প্রয়োজন তখন বরাদ্দ করা মেমরি দ্বিগুণ করে এবং থ্রেড-নিরাপদ দেখায়।
এটিতে কিছু ম্যাক্রো সম্প্রসারণ প্রয়োজন, তবে আপনি আরও ভাল করার সম্ভাবনা কম।
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
প্রস্তাবিত হিসাবে, আপনি নিজের বাফার তৈরি করে কোনও কনসোল থেকে পাঠানোর জন্য getchar () ব্যবহার করতে পারেন an আপনি যদি যুক্তিসঙ্গত সর্বাধিক লাইনের আকার নির্ধারণ করতে না পারেন তবে গতিশীলভাবে বাড়ানো বাফার ঘটতে পারে।
আপনি সি নাল-টার্মিনেটেড স্ট্রিং হিসাবে লাইন পাওয়ার নিরাপদ উপায় হিসাবে fgets ব্যবহার করতে পারেন:
#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 ফিরে আসে এবং লাইন বাফারটি অপরিবর্তিত হতে পারে (এজন্য প্রথম চরটি '\ 0' এ সেট করা কার্যকর)।
fgets লাইন ওভারফিল করবে না] এবং এটি নিশ্চিত করবে যে সফল ফিরতিতে সর্বশেষ গৃহীত চরিত্রের পরে কোনও শূন্যতা রয়েছে।
যদি শেষ অবধি পৌঁছে যায় তবে '\ 0' এর সমাপ্তির আগে থাকা অক্ষরটি '\ n' হবে।
'\ 0' সমাপ্তির আগে যদি কোনও সমাপ্তি '\ n' না থাকে তবে এটি আরও বেশি ডেটা থাকতে পারে বা পরবর্তী অনুরোধটি ফাইল-এর শেষে রিপোর্ট করবে। কোনটি তা নির্ধারণ করতে আপনাকে আরও একটি কল্পিত কাজ করতে হবে। (এক্ষেত্রে, গেটচার () দিয়ে লুপিং করা সহজ)
উপরের (আপডেট করা) উদাহরণ কোডে, লাইন যদি [আকারের (লাইন) -1] == '\ 0' সফল fgets পরে, আপনি জানেন যে বাফার পুরোপুরি পূর্ণ হয়ে গেছে। যদি সেই অবস্থানটি '\ n' দ্বারা চালিত হয় আপনি জানেন আপনি ভাগ্যবান। অন্যথায়, স্ট্যাডিনে আরও ডেটা বা ফাইলের শেষের ব্যবস্থা রয়েছে। (যখন বাফার পুরোপুরি পূরণ করা হয় না, আপনি তখনও ফাইলের শেষের দিকে থাকতে পারেন এবং বর্তমান লাইনের শেষে '\ n' নাও থাকতে পারে Since যেহেতু আপনাকে স্ট্রিংটি সন্ধান করতে হবে এবং / বা স্ট্রিংটি শেষ হওয়ার আগে যে কোনও '\ n' (বাফারে প্রথম '\ 0') মুছে ফেলুন, আমি গেচচার () প্রথম স্থানে ব্যবহার করতে পছন্দ করি)
প্রথম অংশ হিসাবে আপনি যে পরিমাণ পড়ছেন তার চেয়ে এখনও বেশি লাইন থাকার জন্য আপনাকে যা করার দরকার তা করুন। গতিবেগের সাথে বাফার বৃদ্ধির উদাহরণগুলি গেটচার বা fgets দ্বারা কাজ করার জন্য তৈরি করা যেতে পারে। নজরদারি করার জন্য কিছু জটিল এজ রয়েছে (যেমন পরবর্তী ইনপুটটি '\ 0' অবস্থানে স্টোরেজ শুরু করার কথা মনে করে যা বাফার বাড়ানোর আগে পূর্ববর্তী ইনপুটটি শেষ করে))
সি-তে কনসোল থেকে একটি লাইন কীভাবে পড়বেন?
আপনার নিজস্ব ফাংশন তৈরি করা, কনসোল থেকে একটি লাইন পড়া অর্জনে আপনাকে সহায়তা করবে এমন একটি উপায়
প্রয়োজনীয় মেমরির প্রয়োজনীয় পরিমাণ বরাদ্দ করতে আমি গতিশীল মেমরি বরাদ্দ ব্যবহার করছি
যখন আমরা বরাদ্দ মেমরিটি শেষ করতে চলেছি তখন আমরা মেমরির আকার দ্বিগুণ করার চেষ্টা করি
এবং এখানে আমি 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
?
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
শেষ (অথবা যাই হোক না কেন আপনার প্ল্যাটফর্মে ব্যবহার করছে)। স্ট্রিমের পরবর্তী আই / ও অপারেশনের পরে এটি অবৈধ হয়ে যায়।
এটার মতো কিছু:
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;
}
কনসোল থেকে একটি লাইন পড়ার সবচেয়ে সহজ এবং সহজ উপায়টি getchar () ফাংশনটি ব্যবহার করছে, যার মাধ্যমে আপনি একবারে একটি অক্ষরে একটি অ্যারে সংরক্ষণ করবেন store
{
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))
সর্বদা ভুল এবং এটি ভুল ব্যবহারের আরও একটি উদাহরণ।