Lesson 10 learning C language lesson 6: arrays

Game programming 2022-05-14 14:42:07 阅读数:630

lessonlearninglanguagelessonarrays

Preface

Hello everyone , I'm a scroll , The topic of this lesson is arrays , There are many contents in this class , share 14 An example , I hope everyone can stick to . This class mainly includes the following parts ： Output all numbers greater than the average , Find the position of the maximum value in the matrix , Palindrome , Homework .（ Resources and discussion at the end of the course q Group number ）

One 、 Output all numbers greater than the average

example 1： Input 10 It's an integer , Calculate the average of these numbers , Then output all numbers greater than the average . analysis ： This question requires that you output a number greater than the average , So you need to use an array to save this 10 Number . Define a size as 10 Integer array , utilize for loop , Each cycle uses it to save the number of inputs and accumulate the total score . Let me define one more double Type variable avg, Save the average score . use for Loop through each element of the array , Judge whether the current element is greater than each time avg, If so, output . This topic focuses on the definition and use of arrays , Let's take a look at the code ：

``#include<stdio.h>int main(){ int i,sum=0; int a[10]; printf(" Input 10 Number ："); for(i=0;i<10;i++){ scanf("%d",&a[i]); sum+=a[i]; } double avg=sum/10.0; printf(" The average value is ：%.2f\n",avg); printf(" The number greater than the average is as follows ：\n"); for(i=0;i<10;i++){ if(a[i]>avg) printf("%d ",a[i]); } putchar('\n'); return 0;}``

First, define a scale as 10 Array of , Array name a. After this definition , The values of the elements of the array are random . We can try it ：

We can see , The elements of the array are randomly assigned . Array elements can be initialized with curly braces ：

We can see , Uninitialized elements are automatically assigned to 0. That is, if initialization is not done , Element values are random , If initialization is done , Uninitialized elements are automatically assigned to 0. Here is the most important , Array index from 0 Start , That is, you can only access a0 To a9, If you visit a[10], Is that the array subscript is out of bounds , The compiler will report an error . I want to be here , You should have a certain understanding of arrays . The elements of the array are entered like this ：

`` for(i=0;i<10;i++){ scanf("%d",&a[i]); sum+=a[i]; }``

because a[i] It's a variable , So you need the same number . Then add up each element . After that, the code is relatively simple , So let's try that ：

Note here scanf The function takes a space as the separator , That is to say scanf Stop typing as soon as you encounter a space . So input continuously , Several numbers can be separated by spaces . This is the explanation of this topic .
example 2： Calculate the first... Of Fibonacci sequence with array 10 Number , And print five numbers per line . analysis ： The Fibonacci sequence is characterized by the beginning of the third term , Each term is equal to the sum of the first two terms , So the array a The first two items are a0 and a1, And the initial values are 1. The third item starts with a cycle , In the form of iteration , namely a[i]=a[i-1]+a[i-2]. At the end of the cycle ,a The Fibonacci sequence is preserved , Then iterate through the array , Output according to the format required by the topic . The key point of this question is the iteration of array elements , Let's take a look at the code ：

``#include<stdio.h>int main(){ int i,fib[10]={1,1}; for(i=2;i<10;i++) fib[i]=fib[i-1]+fib[i-2]; for(i=0;i<10;i++){ printf("%6d",fib[i]); if((i+1)%5==0) printf("\n"); } return 0;}``

First initialize the array , Assign two terms to 1. After that, each item is added in the form of such iteration , This form is very intuitive , I think everyone should understand . Then output it , model 5 For every output 5 Wrap a line once . Let's take a look at the results ：

This is the front of the Fibonacci sequence 10 The item .
example 3： Input 5 It's an integer , Store them in an array a in , Enter another number x, Then look in the array x. If you find , Output the corresponding minimum subscript , Otherwise output not found. analysis ： The idea of this question is very simple , First define an integer array a, Integer variables x, Then input 5 Number , Put it there a in . Then from the subscript 0 Start traversing array , If the current element is equal to x, To find x, Its subscript is the minimum subscript , Just output . For the convenience of judgment , You can use an integer variable flag, The initial value is 0, If found, set it to 1. such , If after the cycle ,flag be equal to 0 Then... Is not found ,flag be equal to 1 Then it means it is found . Code ：

``#include<stdio.h>int main(){ int i,flag,x; int a[5]; printf(" Input 5 It's an integer ："); for(i=0;i<5;i++) scanf("%d",&a[i]); printf(" Input x："); scanf("%d",&x); flag=0; for(i=0;i<5;i++) if(a[i]==x){ printf(" The subscript is %d\n",i); flag=1; break; } if(flag==0) printf("x Not found ！\n"); return 0;}``

This is the example 3 The code of .for Within the loop , If x Equal to current element , Just output his subscript , Set the sign to 1, And then exit the loop . After exiting the loop , If the flag is not 0, To find . Let's try that ：

This is the explanation of this topic .
example 4： Enter a positive integer n, Input again n It's an integer , Store them in an array a in .
（1） Output min , And its corresponding subscript
（2） The second is to exchange the minimum value with the first number , Output after exchange n Number
analysis ： The first one is very simple , Mainly look at the second . Save the input data in the array a in , Then it's the same as finding the maximum , Find the minimum . Because the title requires the output of subscripts , So there's a simple way . That is, only one integer variable is defined index, Indicates subscript , If you encounter more than a[index] It's a small number a[i],index Update to i. At the end of the cycle a[index] That's the minimum . Two number exchange requires the definition of temporary variables temp, use temp preservation a[index], then a[index] By a[0] Replace , Last a[0] By temp Replace . After the exchange, traverse the array , Just output . The key point of this question is to exchange two elements . Code ：

``#include<stdio.h>int main(){ int i,index,n; int a[10]; printf(" Input n："); scanf("%d",&n); printf(" Input %d Number ：",n); for(i=0;i<n;i++) scanf("%d",&a[i]); index=0; for(i=1;i<n;i++) if(a[i]<a[index]) index=i; printf(" minimum value ：%d, Corresponding subscript %d\n",a[index],index); int temp=a[index]; a[index]=a[0]; a[0]=temp; printf(" After the minimum value is exchanged with the first number ：\n"); for(i=0;i<n;i++) printf("%d ",a[i]); return 0;}``

After entering array elements , We have to start judging . Because the subscript is from 0 At the beginning , So let the subscript of the minimum element be 0. Then loop the variable from 1 Start , If the current element is less than the minimum , Then update the minimum subscript . About exchange elements , First save... With a temporary variable a[index], Why save it ？ Because in the next line, it will be a[0] Replace . And then because temp It's preserved in a[index], So active replacement elements a[0] Re be temp Replace , In this way, the exchange of two numbers is realized . Of course, save it first a[0] It's fine too , In this case ,a[0] It's about to be a[index] Replace , then temp Replace with a[index]. therefore , The pattern of exchanging elements is ： First save a number , The number in the next line is immediately replaced , The last number of active replacement , To be temp Replace with . So let's verify that ：

This is the result of this problem .
example 5： Choose the sorting method . Enter a positive integer n, Input again n It's an integer , Use the selection method to sort them from small to large and output , The steps to select the sorting algorithm are as follows ：
First step ： In unordered n In number , Find the smallest number , With it a[0] In exchange for
The second step ： In the remaining unordered n-1 Find the lowest decimal point in the number , With it a[1] In exchange for
The first n-1 Step ： In the remaining unordered ,2 Find the lowest decimal point in the number , With it a[n-2] In exchange for
analysis ： Selection sort is the same as bubble sort , Are classic algorithms that use double loops . In use array a After saving the integer , use for Loop through groups , Each cycle takes the subscript of the current element i As the minimum subscript k. And then another one for Cycle take a[k] Go and compare the size with the following elements . if a[i] Less than a[k], be k Update to i. At the end of the inner cycle ,k Is the subscript of the smaller element , Re examination k Updated or not , namely k Is it equal to i. If it is equal to the , explain a[i] Still the smallest element . If not equal to , Will a[i] And a[k] In exchange for , Change the latest smallest element to the front . After sorting, traverse the array again , Just output . The focus of this question is obviously to choose and sort , This is also an important sort , I hope you will understand , Instead of just memorizing . Code ：

``#include<stdio.h>int main(){ int n; printf(" Input n："); scanf("%d",&n); int a[n],i; printf(" Input %d Number ：",n); for(i=0;i<n;i++) scanf("%d",&a[i]); int j,k; for(i=0;i<n;i++){ k=i; for(j=k+1;j<n;j++) if(a[j]<a[k]) k=j; if(k!=i){ int temp=a[k]; a[k]=a[i]; a[i]=temp; } } printf(" Sorting result ：\n"); for(i=0;i<n;i++) printf("%d ",a[i]); putchar('\n'); return 0;}``

In circulation , Just start selecting an element , Then compare this element with the following , If there is an element smaller than it , Update the minimum element subscript . Attention , This for Loops have no curly braces , There is only the first scope of execution if. If the subscript of the smallest element has an update , Indicates that the latest smallest element has been found , Then swap the two elements . The core idea of selective sorting is ： Find the smallest element , Throw it to the front . I hope you will keep this sentence in mind , Then deeply understand . Let's take a look at the results ：

example 6： Investigate the popularity of TV programs . A TV station wants to investigate the audience , For this station 8 The popularity of each column , A total of 1000 Audience , Now it is required to write a program , Enter the vote of each audience , Count and output the votes of each column . analysis ： This is a problem of classified statistics , Enter a batch of integers , Output after counting the votes of each column , This requires the cumulative number of votes for each column . This example uses an integer array count Save the votes of each column , Column number corresponding to array subscript . such ,count[1] To count[8] respectively 8 The number of votes for each column , namely count[i] Represents the number i The number of votes for the column . When an audience votes for a column i when , Direct use count[i] Self increasing 1 that will do . The focus of this question is obviously to use arrays to count data , This idea is relatively novel , It is also a more convenient and important idea , I hope you can use it flexibly in future programming . Code ：

``#include<stdio.h>int main(){ int count[9]={0},i,option; for(i=1;i<=10;i++){// For convenience , The upper limit can be set to 10 Wait for smaller numbers printf(" Enter your favorite column number ："); scanf("%d",&option); if(option>=1&&option<=8) count[option]++;// Use the input element as the index of the element else printf(" Invalid number ！\n"); } printf(" The voting results of each column are as follows ：\n"); for(i=1;i<=8;i++) printf(" The column %d：%d ticket \n",i,count[i]); printf("\n"); return 0;}``

Because first of all, the number is 1-8, So define a scale as 9 Array of . For convenience , The upper limit can be set to 10 Wait for smaller numbers , Here might as well be 10. First enter the column number , Every time you decide whether you are 1-8 within , If it is , Index elements with numbers as subscripts , Then the number of votes +1. Use the input number as the index of the element , This is an important idea , Finally, output . Run it ：

This is the explanation of this topic .

Two 、 Find the position of the maximum value in the matrix

example 7： Will a 3x2 The matrix is stored in a 3x2 In a two-dimensional array , Find the maximum value and its row and column subscripts , And output the matrix . analysis ： A binary array int a[m][n], It means a m That's ok n Columns of the matrix , The matrix element is int Type variable . Find the maximum , First we have to traverse the matrix , So use a double loop to traverse a two-dimensional array . Because array subscript from 0 Start , therefore a[i][j] It means the first one i+1 That's ok , The first j+1 The elements of the column . You might as well set the subscript of the maximum row to row, The column subscript is col, The algorithm is similar to finding the maximum value of one-dimensional array . Compare a[row][col] And a[i][j], Just update the subscript . The maximum value after the end of the cycle is naturally a[row][col], Traverse the two-dimensional array again , Just output each element . The key point of this question is , Obviously, it is the definition and use of two-dimensional array . Code ：

``#include<stdio.h>int main(){ int i,j,a[3][2]; printf(" Input 6 It's an integer ：\n"); for(i=0;i<3;i++) for(j=0;j<2;j++) scanf("%d",&a[i][j]); printf(" The resulting matrix is as follows ：\n"); for(i=0;i<3;i++){ for(j=0;j<2;j++) printf("%4d",a[i][j]); printf("\n"); } int row=0,col=0; for(i=0;i<3;i++) for(j=0;j<2;j++) if(a[row][col]<a[i][j]){ row=i; col=j; } printf("\nmax=a[%d][%d]=%d\n",row,col,a[row][col]); return 0;}``

So we define one 3 That's ok 2 Columns of the matrix , Initialization of 2D array , Need two curly braces , Like this ：

``int a[3][2]={{1,2},{2,3},{3,1}};``

We can see that , The first dimension is 3 Elements , The second dimension has two elements . Every element of the first dimension , It's all a one-dimensional array , The second dimension is numbers . It's easy to understand , Two dimensional arrays are also arrays , But its element itself is also an array .[3][2] It means that the first dimension has at most 3 Elements , The second dimension has at most 2 Elements , This is the concept of two-dimensional array . Enter the elements of the two-dimensional array ：

`` for(i=0;i<3;i++) for(j=0;j<2;j++) scanf("%d",&a[i][j]);``

This is actually similar to the input of one-dimensional array , It's just one more layer of circulation , Just one more variable . Find the most valuable code ：

`` int row=0,col=0; for(i=0;i<3;i++) for(j=0;j<2;j++) if(a[row][col]<a[i][j]){ row=i; col=j; }``

The algorithm here is similar to that of one-dimensional array , Just one more cycle , Just one more variable . So let's run this ：

This is the result of this question .
example 8： Define a 3x2 A binary array of a, The values of array elements are given by the following formula ：a[i][j]=i+j; Output in matrix form a. analysis ： The problem is simple , Define a two-dimensional array , Assign a value to the formula according to the title . And then go through it again , Output each element of the matrix . Because the problem is relatively simple , No explanation here .
example 9：

You can see , The transposed square matrix in the example , Diagonal elements don't change , But the elements on both sides of the diagonal are interchangeable . The first half of this question is very simple , Assign values according to the requirements of the topic . In the second half, we should understand the characteristics of square matrix transpose , Swap the two elements next to the diagonal . In Linear Algebra （ One of College Mathematics ） in , The diagonal and above of a matrix is called an upper triangular matrix , The diagonal and below is called the lower triangular matrix . Because you only need to change ranks once , So just traverse the upper triangular matrix or the lower triangular matrix . Take the triangular array above as an example , Because diagonal elements do not need to be traversed , Therefore, the column number of the element to be exchanged must be greater than the row number . That is, select the i That's ok , And the column number of the next element j>i, That is to say j from i+1 To traverse the . The lower triangular matrix is the opposite ,j<i, The key point of this question is the transposition of square matrix . Code ：

``#include<stdio.h>int main(){ int i,j,n; printf(" Input n："); scanf("%d",&n); int a[n][n]; for(i=0;i<n;i++) for(j=0;j<n;j++) a[i][j]=i*n+j+1; for(i=0;i<n;i++) for(j=i+1;j<n;j++){ int temp=a[i][j]; a[i][j]=a[j][i]; a[j][i]=temp; } for(i=0;i<n;i++){ for(j=0;j<n;j++) printf("%4d",a[i][j]); printf("\n"); } return 0;}``

The core of the transpose matrix is . Take the triangular array above as an example , Column number j It is greater than i Of , therefore j from i+1 Start , And then swap i,j The element at , The final output , So let's verify that ：

This is the result of this question .
example 10：

analysis ： First of all, the number of days in leap years and normal years is different , So use a two-dimensional array tab To store the number of days per month ,tab There are two elements in the first dimension of , The number of days of a month in a normal year , Another one stores the number of days of each month in leap years . For convenience , The subscript of the second dimension is from 1 Start , therefore tab The form of definition is int tab[2][13], And then define variables leap, Receive the result of whether it is a leap year . use leap As tab The first dimensional subscript of , Utilization cycle , Number of days passed in .day De accumulation tab[leap][i], At the end of the cycle day Is the number of days in the month + The number of days in the previous month , That is, how many days passed that year . The key point of this question is the application of two-dimensional array . This is the code of this problem ：

``#include<stdio.h>int day_of_year(int year,int month,int day){ int k,leap; int tab[2][13]={ {0,31,28,31,30,31,30,31,31,30,31,30,31}, {0,31,29,31,30,31,30,31,31,30,31,30,31} }; leap=((year%4==0&&year%100!=0)||year%400==0); for(k=1;k<month;k++) day+=tab[leap][k]; return day;}int main(){ int year,month,day; printf(" Enter year , month , Japan ："); scanf("%d %d %d",&year,&month,&day); int total=day_of_year(year,month,day); printf(" It is the... Of the year %d God \n",total); return 0;}``

The first dimension of this two-dimensional array is the number of days per month in normal years , The second of the first dimension is the number of days per month in leap years . Then decide whether leap year or ordinary year , If it's a leap year , So the result is 1, It locates the second element of the first dimension . If it's a normal year , The result is 0, It locates the first element of the first dimension . Then the number of days passed in plus the number of days of each month . Note that there k To reach month, for instance 3 month 15 Japan , So it's going to be 15 Heaven plus 1 Days of the month , add 2 Days of the month , If you add 3 The number of days in the month is wrong , So let's verify that ：

This is the explanation of this topic .

3、 ... and 、 Palindrome

example 11： Enter a string ending with carriage return , Judge whether the letter is called palindrome , Palindromes are strings , Centrosymmetry , Such as abcba,abccba It's palindrome. ,abcdba Not a palindrome . analysis ：C In language , Strings need to be stored in character arrays , And the most questions 80 Characters , So you might as well define a character array line[80] To receive characters . Judging palindromes is simple , Just two subscripts , From the middle to both sides , Just decide . There are two types of string input , One is through scanf, With %s Receive an entire string in the form of . Another is to use getchar() Enter the characters one by one , Because the end symbol of this question is the Enter key ,scanf End with carriage return again , So both ways can . If the sign is another character , You can only use getchar(). Here you might as well use getchar(), Use a cycle , When the received character is the Enter key, it exits the cycle . Generally, integer variables are used to mark the position of characters in the array , such as k. At the end of the cycle ,k Where you are, you can fill in the ending character , It can also be left blank , Because the title does not require the output of a whole string . then i from 0 Start ,k reduce ,k It becomes the end position .i and k From both ends to the middle , until i and k The elements of the position are not equal or i and k meet . Obviously, the key point of using one-dimensional character array is the definition of one-dimensional character array . Code ：

``#include<stdio.h>int main(){ int i,k; char line[80]; printf(" Enter a string ：\n"); k=0; while((line[k]=getchar())!='\n') k++; i=0; k=k-1; while(i!=k){ if(line[i]!=line[k]) break; i++; k--; } if(i>=k) printf(" It's a palindrome string ！\n"); else printf(" It's not a palindrome string \n"); return 0;}``

First line It's an array of characters , It can store 79 Characters plus 1 Terminator . The terminator is a backslash 0：’\0’. Every character array defined , Will automatically add a terminator at the end , ad locum ,line[79] Is the terminator ,line[0] ~ line[78], The former 79 A place to store characters other than the Terminator . Whether in the printf In or out scanf in , The format of the character array is always %s. If the character array is in %s Format output , Will be marked with the first terminator . That is, if there are multiple terminators in the array , Then output to the first terminator , No output later . This is the basic concept of one-dimensional character array , First use getchar() To input ：

`` k=0; while((line[k]=getchar())!='\n') k++;``

If you encounter a carriage return , Just close the loop , Otherwise, the characters are stored in the array line.k It's a subscript , Add... For each character stored 1. At the end of the cycle ,k It is equal to the number of characters entered , That is, the input length of the character array , That is, the last position of the input array . Because there is no need to printf Output an entire character array , therefore line[k] You can put the Terminator , Or you can leave it alone . Due to the input of k Elements , So elements should be stored in line[0]~line[k-1], therefore k want -1, Point to the location of the last valid element . Then it is to determine the palindrome string ：

`` i=0; k=k-1; while(i!=k){ if(line[i]!=line[k]) break; i++; k--; }``

i and k From both ends of the array to the middle , When two elements are unequal or i and k meet , At the end of the scan , The loop ends . If i<k, The scan is not over , That is, the two elements are unequal , Indicates that it is not a palindrome string . Otherwise, the scanning is over , Everything is all right , No two letters are not equal , It's a palindrome string . So let's verify that ：

This is the explanation of this topic .
example 12： Enter a string ending with carriage return （ Less than 80 Characters ）, Count the number of numeric characters . example 13： Enter a string ending with carriage return （ Less than 10 Characters ）, Extract all numeric characters , Convert it to a decimal integer output . analysis ： The input of these two questions is the same , And it's almost the same as the last question , I won't repeat . example 12 Relatively simple , No explanation . The difference between these two questions lies in the operation of traversal , example 12 It's statistics , example 13 Is to convert the digital part into 10 Hexadecimal integer . The statistics are simple , The main thing is to get 10 Hexadecimal number . First, define an integer variable num be equal to 0, Assume that the numeric character currently traversed is ch, be num=num*10+ch-’0’. according to ASC The law of code table , Numeric characters are represented in decimal , And in continuous ascending order . So subtract the character from any numeric character 0 Is the decimal number of the difference , Like characters 1 And character 0, stay ASC The decimal system in the code table indicates the difference 1, So directly subtract to get the character 1 The corresponding integer 1. example 13 The focus is obviously on converting numeric strings to decimal integers . Code ：

``#include<stdio.h>int main(){ int i; char str[10]; printf(" Enter a string ：\n"); i=0; while((str[i]=getchar())!='\n') i++; int num=0,j; for(j=0;j<i;j++) if(str[j]<='9'&&str[j]>='0') num=num*10+(str[j]-'0'); printf(" The result is ：%d\n",num); return 0;}``

Within the loop , Determine whether it is a number , If it's a number , Then it is converted to decimal integer . So let's verify that ：

This is the explanation of this topic .

``#include<stdio.h>int bt0_9(char ch);int bta_z(char ch);int btA_Z(char ch);int main(){ int i,k; char hex[80],str[80]; printf(" Enter a string ："); i=0; while((str[i]=getchar())!='#') i++; str[i]='\0'; i=k=0; while(str[i]!='\0'){ if(bt0_9(str[i])||btA_Z(str[i])||bta_z(str[i])) hex[k++]=str[i];//k++ Add the following symbol ++ // Later increase ： After assignment +1, It's increasing ：+1 Post assignment i++; } hex[k]='\0'; printf(" New string ："); printf("%s",hex); putchar('\n'); long num=0;// Long integer ：long 8bytes for(i=0;hex[i]!='\0';i++){ if(bt0_9(hex[i])) num=num*16+hex[i]-'0'; else if(bta_z(hex[i])) num=num*16+hex[i]-'a'+10; else num=num*16+hex[i]-'A'+10; } printf(" To 16 In the system ：%ld\n",num); return 0;}int bt0_9(char ch){ return ch>='0'&&ch<='9';}int bta_z(char ch){ return ch>='a'&&ch<='z';}int btA_Z(char ch){ return ch>='A'&&ch<='Z';}``

I define three functions here , Used to determine the number , Lowercase and capital letters ：

``int bt0_9(char ch){ return ch>='0'&&ch<='9';}int bta_z(char ch){ return ch>='a'&&ch<='z';}int btA_Z(char ch){ return ch>='A'&&ch<='Z';}``

Scan the input string , When the element of the string is not a Terminator , Just execute the loop , This kind of expression is relatively simple . When the input is not finished , determine , If the current character is one of numbers and English letters , Then add this character to the new character array hex in ：

`` if(bt0_9(str[i])||btA_Z(str[i])||bta_z(str[i])) hex[k++]=str[i];//k++ Add the following symbol ++ // Later increase ： After assignment +1, It's increasing ：+1 Post assignment ``

Particular attention ： The addition here is the post addition sign , Its function is to add... After assignment 1, If it's a leading sign , Its function is to increase and then assign values , That's wrong . At the end of the loop, you get the hexadecimal string , That is, a string containing only numbers or English letters , To output this part , Add a terminator at the end ：

`` hex[k]='\0'; printf(" New string ："); printf("%s",hex); putchar('\n');``

Then hexadecimal , Because the number converted to hexadecimal may be large , So here's a long integer long, It takes up 8 Bytes . The output format of long shaping is %ld. The formula to hexadecimal has been mentioned earlier , Let's not talk about it here , So let's verify that ：

Okay , This is the whole explanation of the example .

Four 、 Homework

Let's take a look at the homework , The homework is 14 Add... To the example 1 Exercises , in total 15 Problem . practice 1：

This question is similar to the voting question , Their core idea is the same , It's all in one count Array , It's just that the count The scale is 10. Of course count When the array is initialized , To initialize to 0 Oh , Or you can set this array as a global variable array , Global variable or global variable array , Its elements are automatically initialized to zero . Okay , That's all this talk is about , I'll see you next ！
After class homework and reference answers Extraction code ：l2du
Discuss group numbers ：1028887052
author ： Technical volume

Game programming , A game development favorite ~

If the picture is not displayed for a long time , Please use Chrome Kernel browser .